]> granicus.if.org Git - python/commitdiff
bpo-32069: Drop legacy SSL transport (#4451)
authorAndrew Svetlov <andrew.svetlov@gmail.com>
Sat, 18 Nov 2017 16:54:05 +0000 (18:54 +0200)
committerGitHub <noreply@github.com>
Sat, 18 Nov 2017 16:54:05 +0000 (18:54 +0200)
* Drop legacy SSL transport

* Drop unused import

* Fix Windows tests

* Drop never executed on Python 3.4+ code

Lib/asyncio/proactor_events.py
Lib/asyncio/selector_events.py
Lib/asyncio/sslproto.py
Lib/asyncio/test_utils.py
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_selector_events.py
Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst [new file with mode: 0644]

index 5e7a39727cce2ec7cecf50242cb29e06cd34e016..e35d05b7bf0ba2a37c30ceff26ac737e1bdc5700 100644 (file)
@@ -392,11 +392,6 @@ class BaseProactorEventLoop(base_events.BaseEventLoop):
     def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
                             *, server_side=False, server_hostname=None,
                             extra=None, server=None):
-        if not sslproto._is_sslproto_available():
-            raise NotImplementedError("Proactor event loop requires Python 3.5"
-                                      " or newer (ssl.MemoryBIO) to support "
-                                      "SSL")
-
         ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
                                             server_side, server_hostname)
         _ProactorSocketTransport(self, rawsock, ssl_protocol,
index f3b278c9ea73c3e4e5c996940a5c32fe17946f2b..4baad48ce39d2c13f2209b29ae47533b445c5122 100644 (file)
@@ -74,28 +74,12 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
     def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
                             *, server_side=False, server_hostname=None,
                             extra=None, server=None):
-        if not sslproto._is_sslproto_available():
-            return self._make_legacy_ssl_transport(
-                rawsock, protocol, sslcontext, waiter,
-                server_side=server_side, server_hostname=server_hostname,
-                extra=extra, server=server)
-
         ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
                                             server_side, server_hostname)
         _SelectorSocketTransport(self, rawsock, ssl_protocol,
                                  extra=extra, server=server)
         return ssl_protocol._app_transport
 
-    def _make_legacy_ssl_transport(self, rawsock, protocol, sslcontext,
-                                   waiter, *,
-                                   server_side=False, server_hostname=None,
-                                   extra=None, server=None):
-        # Use the legacy API: SSL_write, SSL_read, etc. The legacy API is used
-        # on Python 3.4 and older, when ssl.MemoryBIO is not available.
-        return _SelectorSslTransport(
-            self, rawsock, protocol, sslcontext, waiter,
-            server_side, server_hostname, extra, server)
-
     def _make_datagram_transport(self, sock, protocol,
                                  address=None, waiter=None, extra=None):
         return _SelectorDatagramTransport(self, sock, protocol,
@@ -848,238 +832,6 @@ class _SelectorSocketTransport(_SelectorTransport):
         return True
 
 
-class _SelectorSslTransport(_SelectorTransport):
-
-    _buffer_factory = bytearray
-
-    def __init__(self, loop, rawsock, protocol, sslcontext, waiter=None,
-                 server_side=False, server_hostname=None,
-                 extra=None, server=None):
-        if ssl is None:
-            raise RuntimeError('stdlib ssl module not available')
-
-        if not sslcontext:
-            sslcontext = sslproto._create_transport_context(server_side, server_hostname)
-
-        wrap_kwargs = {
-            'server_side': server_side,
-            'do_handshake_on_connect': False,
-        }
-        if server_hostname and not server_side:
-            wrap_kwargs['server_hostname'] = server_hostname
-        sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
-
-        super().__init__(loop, sslsock, protocol, extra, server)
-        # the protocol connection is only made after the SSL handshake
-        self._protocol_connected = False
-
-        self._server_hostname = server_hostname
-        self._waiter = waiter
-        self._sslcontext = sslcontext
-        self._paused = False
-
-        # SSL-specific extra info.  (peercert is set later)
-        self._extra.update(sslcontext=sslcontext)
-
-        if self._loop.get_debug():
-            logger.debug("%r starts SSL handshake", self)
-            start_time = self._loop.time()
-        else:
-            start_time = None
-        self._on_handshake(start_time)
-
-    def _wakeup_waiter(self, exc=None):
-        if self._waiter is None:
-            return
-        if not self._waiter.cancelled():
-            if exc is not None:
-                self._waiter.set_exception(exc)
-            else:
-                self._waiter.set_result(None)
-        self._waiter = None
-
-    def _on_handshake(self, start_time):
-        try:
-            self._sock.do_handshake()
-        except ssl.SSLWantReadError:
-            self._loop._add_reader(self._sock_fd,
-                                   self._on_handshake, start_time)
-            return
-        except ssl.SSLWantWriteError:
-            self._loop._add_writer(self._sock_fd,
-                                   self._on_handshake, start_time)
-            return
-        except BaseException as exc:
-            if self._loop.get_debug():
-                logger.warning("%r: SSL handshake failed",
-                               self, exc_info=True)
-            self._loop._remove_reader(self._sock_fd)
-            self._loop._remove_writer(self._sock_fd)
-            self._sock.close()
-            self._wakeup_waiter(exc)
-            if isinstance(exc, Exception):
-                return
-            else:
-                raise
-
-        self._loop._remove_reader(self._sock_fd)
-        self._loop._remove_writer(self._sock_fd)
-
-        peercert = self._sock.getpeercert()
-        if not hasattr(self._sslcontext, 'check_hostname'):
-            # Verify hostname if requested, Python 3.4+ uses check_hostname
-            # and checks the hostname in do_handshake()
-            if (self._server_hostname and
-                self._sslcontext.verify_mode != ssl.CERT_NONE):
-                try:
-                    ssl.match_hostname(peercert, self._server_hostname)
-                except Exception as exc:
-                    if self._loop.get_debug():
-                        logger.warning("%r: SSL handshake failed "
-                                       "on matching the hostname",
-                                       self, exc_info=True)
-                    self._sock.close()
-                    self._wakeup_waiter(exc)
-                    return
-
-        # Add extra info that becomes available after handshake.
-        self._extra.update(peercert=peercert,
-                           cipher=self._sock.cipher(),
-                           compression=self._sock.compression(),
-                           ssl_object=self._sock,
-                           )
-
-        self._read_wants_write = False
-        self._write_wants_read = False
-        self._loop._add_reader(self._sock_fd, self._read_ready)
-        self._protocol_connected = True
-        self._loop.call_soon(self._protocol.connection_made, self)
-        # only wake up the waiter when connection_made() has been called
-        self._loop.call_soon(self._wakeup_waiter)
-
-        if self._loop.get_debug():
-            dt = self._loop.time() - start_time
-            logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
-
-    def pause_reading(self):
-        # XXX This is a bit icky, given the comment at the top of
-        # _read_ready().  Is it possible to evoke a deadlock?  I don't
-        # know, although it doesn't look like it; write() will still
-        # accept more data for the buffer and eventually the app will
-        # call resume_reading() again, and things will flow again.
-
-        if self._closing:
-            raise RuntimeError('Cannot pause_reading() when closing')
-        if self._paused:
-            raise RuntimeError('Already paused')
-        self._paused = True
-        self._loop._remove_reader(self._sock_fd)
-        if self._loop.get_debug():
-            logger.debug("%r pauses reading", self)
-
-    def resume_reading(self):
-        if not self._paused:
-            raise RuntimeError('Not paused')
-        self._paused = False
-        if self._closing:
-            return
-        self._loop._add_reader(self._sock_fd, self._read_ready)
-        if self._loop.get_debug():
-            logger.debug("%r resumes reading", self)
-
-    def _read_ready(self):
-        if self._conn_lost:
-            return
-        if self._write_wants_read:
-            self._write_wants_read = False
-            self._write_ready()
-
-            if self._buffer:
-                self._loop._add_writer(self._sock_fd, self._write_ready)
-
-        try:
-            data = self._sock.recv(self.max_size)
-        except (BlockingIOError, InterruptedError, ssl.SSLWantReadError):
-            pass
-        except ssl.SSLWantWriteError:
-            self._read_wants_write = True
-            self._loop._remove_reader(self._sock_fd)
-            self._loop._add_writer(self._sock_fd, self._write_ready)
-        except Exception as exc:
-            self._fatal_error(exc, 'Fatal read error on SSL transport')
-        else:
-            if data:
-                self._protocol.data_received(data)
-            else:
-                try:
-                    if self._loop.get_debug():
-                        logger.debug("%r received EOF", self)
-                    keep_open = self._protocol.eof_received()
-                    if keep_open:
-                        logger.warning('returning true from eof_received() '
-                                       'has no effect when using ssl')
-                finally:
-                    self.close()
-
-    def _write_ready(self):
-        if self._conn_lost:
-            return
-        if self._read_wants_write:
-            self._read_wants_write = False
-            self._read_ready()
-
-            if not (self._paused or self._closing):
-                self._loop._add_reader(self._sock_fd, self._read_ready)
-
-        if self._buffer:
-            try:
-                n = self._sock.send(self._buffer)
-            except (BlockingIOError, InterruptedError, ssl.SSLWantWriteError):
-                n = 0
-            except ssl.SSLWantReadError:
-                n = 0
-                self._loop._remove_writer(self._sock_fd)
-                self._write_wants_read = True
-            except Exception as exc:
-                self._loop._remove_writer(self._sock_fd)
-                self._buffer.clear()
-                self._fatal_error(exc, 'Fatal write error on SSL transport')
-                return
-
-            if n:
-                del self._buffer[:n]
-
-        self._maybe_resume_protocol()  # May append to buffer.
-
-        if not self._buffer:
-            self._loop._remove_writer(self._sock_fd)
-            if self._closing:
-                self._call_connection_lost(None)
-
-    def write(self, data):
-        if not isinstance(data, (bytes, bytearray, memoryview)):
-            raise TypeError('data argument must be a bytes-like object, '
-                            'not %r' % type(data).__name__)
-        if not data:
-            return
-
-        if self._conn_lost:
-            if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
-                logger.warning('socket.send() raised exception.')
-            self._conn_lost += 1
-            return
-
-        if not self._buffer:
-            self._loop._add_writer(self._sock_fd, self._write_ready)
-
-        # Add it to the buffer.
-        self._buffer.extend(data)
-        self._maybe_pause_protocol()
-
-    def can_write_eof(self):
-        return False
-
-
 class _SelectorDatagramTransport(_SelectorTransport):
 
     _buffer_factory = collections.deque
index 53e6d2b667b12cd179dc7da6054650d6cc732bff..c231eb58ee590a004f48f18d9e6013e090e5c2eb 100644 (file)
@@ -18,25 +18,13 @@ def _create_transport_context(server_side, server_hostname):
     # Client side may pass ssl=True to use a default
     # context; in that case the sslcontext passed is None.
     # The default is secure for client connections.
-    if hasattr(ssl, 'create_default_context'):
-        # Python 3.4+: use up-to-date strong settings.
-        sslcontext = ssl.create_default_context()
-        if not server_hostname:
-            sslcontext.check_hostname = False
-    else:
-        # Fallback for Python 3.3.
-        sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
-        sslcontext.options |= ssl.OP_NO_SSLv2
-        sslcontext.options |= ssl.OP_NO_SSLv3
-        sslcontext.set_default_verify_paths()
-        sslcontext.verify_mode = ssl.CERT_REQUIRED
+    # Python 3.4+: use up-to-date strong settings.
+    sslcontext = ssl.create_default_context()
+    if not server_hostname:
+        sslcontext.check_hostname = False
     return sslcontext
 
 
-def _is_sslproto_available():
-    return hasattr(ssl, "MemoryBIO")
-
-
 # States of an _SSLPipe.
 _UNWRAPPED = "UNWRAPPED"
 _DO_HANDSHAKE = "DO_HANDSHAKE"
index c9b19825f20619b92e14b4463aaf6c7bf5a99056..c3ddfe37563a6a40f8eb791ee66dec8be508a179 100644 (file)
@@ -508,8 +508,3 @@ def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM,
     sock.family = family
     sock.gettimeout.return_value = 0.0
     return sock
-
-
-def force_legacy_ssl_support():
-    return mock.patch('asyncio.sslproto._is_sslproto_available',
-                      return_value=False)
index 5394ddfce24b566c2822ee3db302560b1e5f87db..1a8bc13429648f430ffc0af4f626ef84428b712c 100644 (file)
@@ -736,10 +736,6 @@ class EventLoopTestsMixin:
             self._test_create_ssl_connection(httpd, create_connection,
                                              peername=httpd.address)
 
-    def test_legacy_create_ssl_connection(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_ssl_connection()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
     def test_create_ssl_unix_connection(self):
@@ -757,10 +753,6 @@ class EventLoopTestsMixin:
                                              check_sockname,
                                              peername=httpd.address)
 
-    def test_legacy_create_ssl_unix_connection(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_ssl_unix_connection()
-
     def test_create_connection_local_addr(self):
         with test_utils.run_test_server() as httpd:
             port = support.find_unused_port()
@@ -1061,10 +1053,6 @@ class EventLoopTestsMixin:
         # stop serving
         server.close()
 
-    def test_legacy_create_server_ssl(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_server_ssl()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
     def test_create_unix_server_ssl(self):
@@ -1096,10 +1084,6 @@ class EventLoopTestsMixin:
         # stop serving
         server.close()
 
-    def test_legacy_create_unix_server_ssl(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_unix_server_ssl()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     def test_create_server_ssl_verify_failed(self):
         proto = MyProto(loop=self.loop)
@@ -1129,10 +1113,6 @@ class EventLoopTestsMixin:
         self.assertIsNone(proto.transport)
         server.close()
 
-    def test_legacy_create_server_ssl_verify_failed(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_server_ssl_verify_failed()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
     def test_create_unix_server_ssl_verify_failed(self):
@@ -1163,11 +1143,6 @@ class EventLoopTestsMixin:
         self.assertIsNone(proto.transport)
         server.close()
 
-
-    def test_legacy_create_unix_server_ssl_verify_failed(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_unix_server_ssl_verify_failed()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     def test_create_server_ssl_match_failed(self):
         proto = MyProto(loop=self.loop)
@@ -1196,10 +1171,6 @@ class EventLoopTestsMixin:
         proto.transport.close()
         server.close()
 
-    def test_legacy_create_server_ssl_match_failed(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_server_ssl_match_failed()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
     def test_create_unix_server_ssl_verified(self):
@@ -1226,10 +1197,6 @@ class EventLoopTestsMixin:
         server.close()
         self.loop.run_until_complete(proto.done)
 
-    def test_legacy_create_unix_server_ssl_verified(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_unix_server_ssl_verified()
-
     @unittest.skipIf(ssl is None, 'No ssl module')
     def test_create_server_ssl_verified(self):
         proto = MyProto(loop=self.loop)
@@ -1259,10 +1226,6 @@ class EventLoopTestsMixin:
         server.close()
         self.loop.run_until_complete(proto.done)
 
-    def test_legacy_create_server_ssl_verified(self):
-        with test_utils.force_legacy_ssl_support():
-            self.test_create_server_ssl_verified()
-
     def test_create_server_sock(self):
         proto = asyncio.Future(loop=self.loop)
 
@@ -2159,37 +2122,6 @@ if sys.platform == 'win32':
         def create_event_loop(self):
             return asyncio.ProactorEventLoop()
 
-        if not sslproto._is_sslproto_available():
-            def test_create_ssl_connection(self):
-                raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
-            def test_create_server_ssl(self):
-                raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
-            def test_create_server_ssl_verify_failed(self):
-                raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
-            def test_create_server_ssl_match_failed(self):
-                raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
-            def test_create_server_ssl_verified(self):
-                raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
-        def test_legacy_create_ssl_connection(self):
-            raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
-        def test_legacy_create_server_ssl(self):
-            raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
-        def test_legacy_create_server_ssl_verify_failed(self):
-            raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
-        def test_legacy_create_server_ssl_match_failed(self):
-            raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
-        def test_legacy_create_server_ssl_verified(self):
-            raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
         def test_reader_callback(self):
             raise unittest.SkipTest("IocpEventLoop does not have add_reader()")
 
index a3d118e18812f28e4d108872682b7075d739d80d..e67afcc72040989f4dd9feea3a61bdc574f4d0fa 100644 (file)
@@ -14,7 +14,6 @@ from asyncio import selectors
 from asyncio import test_utils
 from asyncio.selector_events import BaseSelectorEventLoop
 from asyncio.selector_events import _SelectorTransport
-from asyncio.selector_events import _SelectorSslTransport
 from asyncio.selector_events import _SelectorSocketTransport
 from asyncio.selector_events import _SelectorDatagramTransport
 
@@ -1178,368 +1177,6 @@ class SelectorSocketTransportTests(test_utils.TestCase):
         remove_writer.assert_called_with(self.sock_fd)
 
 
-@unittest.skipIf(ssl is None, 'No ssl module')
-class SelectorSslTransportTests(test_utils.TestCase):
-
-    def setUp(self):
-        super().setUp()
-        self.loop = self.new_test_loop()
-        self.protocol = test_utils.make_test_protocol(asyncio.Protocol)
-        self.sock = mock.Mock(socket.socket)
-        self.sock.fileno.return_value = 7
-        self.sslsock = mock.Mock()
-        self.sslsock.fileno.return_value = 1
-        self.sslcontext = mock.Mock()
-        self.sslcontext.wrap_socket.return_value = self.sslsock
-
-    def ssl_transport(self, waiter=None, server_hostname=None):
-        transport = _SelectorSslTransport(self.loop, self.sock, self.protocol,
-                                          self.sslcontext, waiter=waiter,
-                                          server_hostname=server_hostname)
-        self.addCleanup(close_transport, transport)
-        return transport
-
-    def _make_one(self, create_waiter=None):
-        transport = self.ssl_transport()
-        self.sock.reset_mock()
-        self.sslsock.reset_mock()
-        self.sslcontext.reset_mock()
-        self.loop.reset_counters()
-        return transport
-
-    def test_on_handshake(self):
-        waiter = asyncio.Future(loop=self.loop)
-        tr = self.ssl_transport(waiter=waiter)
-        self.assertTrue(self.sslsock.do_handshake.called)
-        self.loop.assert_reader(1, tr._read_ready)
-        test_utils.run_briefly(self.loop)
-        self.assertIsNone(waiter.result())
-
-    def test_on_handshake_reader_retry(self):
-        self.loop.set_debug(False)
-        self.sslsock.do_handshake.side_effect = ssl.SSLWantReadError
-        transport = self.ssl_transport()
-        self.loop.assert_reader(1, transport._on_handshake, None)
-
-    def test_on_handshake_writer_retry(self):
-        self.loop.set_debug(False)
-        self.sslsock.do_handshake.side_effect = ssl.SSLWantWriteError
-        transport = self.ssl_transport()
-        self.loop.assert_writer(1, transport._on_handshake, None)
-
-    def test_on_handshake_exc(self):
-        exc = ValueError()
-        self.sslsock.do_handshake.side_effect = exc
-        with test_utils.disable_logger():
-            waiter = asyncio.Future(loop=self.loop)
-            self.ssl_transport(waiter=waiter)
-        self.assertTrue(waiter.done())
-        self.assertIs(exc, waiter.exception())
-        self.assertTrue(self.sslsock.close.called)
-
-    def test_on_handshake_base_exc(self):
-        waiter = asyncio.Future(loop=self.loop)
-        transport = self.ssl_transport(waiter=waiter)
-        exc = BaseException()
-        self.sslsock.do_handshake.side_effect = exc
-        with test_utils.disable_logger():
-            self.assertRaises(BaseException, transport._on_handshake, 0)
-        self.assertTrue(self.sslsock.close.called)
-        self.assertTrue(waiter.done())
-        self.assertIs(exc, waiter.exception())
-
-    def test_cancel_handshake(self):
-        # Python issue #23197: cancelling a handshake must not raise an
-        # exception or log an error, even if the handshake failed
-        waiter = asyncio.Future(loop=self.loop)
-        transport = self.ssl_transport(waiter=waiter)
-        waiter.cancel()
-        exc = ValueError()
-        self.sslsock.do_handshake.side_effect = exc
-        with test_utils.disable_logger():
-            transport._on_handshake(0)
-        transport.close()
-        test_utils.run_briefly(self.loop)
-
-    def test_pause_resume_reading(self):
-        tr = self._make_one()
-        self.assertFalse(tr._paused)
-        self.loop.assert_reader(1, tr._read_ready)
-        tr.pause_reading()
-        self.assertTrue(tr._paused)
-        self.assertFalse(1 in self.loop.readers)
-        tr.resume_reading()
-        self.assertFalse(tr._paused)
-        self.loop.assert_reader(1, tr._read_ready)
-        with self.assertRaises(RuntimeError):
-            tr.resume_reading()
-
-    def test_write(self):
-        transport = self._make_one()
-        transport.write(b'data')
-        self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
-    def test_write_bytearray(self):
-        transport = self._make_one()
-        data = bytearray(b'data')
-        transport.write(data)
-        self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-        self.assertEqual(data, bytearray(b'data'))  # Hasn't been mutated.
-        self.assertIsNot(data, transport._buffer)  # Hasn't been incorporated.
-
-    def test_write_memoryview(self):
-        transport = self._make_one()
-        data = memoryview(b'data')
-        transport.write(data)
-        self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
-    def test_write_no_data(self):
-        transport = self._make_one()
-        transport._buffer.extend(b'data')
-        transport.write(b'')
-        self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
-    def test_write_str(self):
-        transport = self._make_one()
-        self.assertRaises(TypeError, transport.write, 'str')
-
-    def test_write_closing(self):
-        transport = self._make_one()
-        transport.close()
-        self.assertEqual(transport._conn_lost, 1)
-        transport.write(b'data')
-        self.assertEqual(transport._conn_lost, 2)
-
-    @mock.patch('asyncio.selector_events.logger')
-    def test_write_exception(self, m_log):
-        transport = self._make_one()
-        transport._conn_lost = 1
-        transport.write(b'data')
-        self.assertEqual(transport._buffer, list_to_buffer())
-        transport.write(b'data')
-        transport.write(b'data')
-        transport.write(b'data')
-        transport.write(b'data')
-        m_log.warning.assert_called_with('socket.send() raised exception.')
-
-    def test_read_ready_recv(self):
-        self.sslsock.recv.return_value = b'data'
-        transport = self._make_one()
-        transport._read_ready()
-        self.assertTrue(self.sslsock.recv.called)
-        self.assertEqual((b'data',), self.protocol.data_received.call_args[0])
-
-    def test_read_ready_write_wants_read(self):
-        self.loop._add_writer = mock.Mock()
-        self.sslsock.recv.side_effect = BlockingIOError
-        transport = self._make_one()
-        transport._write_wants_read = True
-        transport._write_ready = mock.Mock()
-        transport._buffer.extend(b'data')
-        transport._read_ready()
-
-        self.assertFalse(transport._write_wants_read)
-        transport._write_ready.assert_called_with()
-        self.loop._add_writer.assert_called_with(
-            transport._sock_fd, transport._write_ready)
-
-    def test_read_ready_recv_eof(self):
-        self.sslsock.recv.return_value = b''
-        transport = self._make_one()
-        transport.close = mock.Mock()
-        transport._read_ready()
-        transport.close.assert_called_with()
-        self.protocol.eof_received.assert_called_with()
-
-    def test_read_ready_recv_conn_reset(self):
-        err = self.sslsock.recv.side_effect = ConnectionResetError()
-        transport = self._make_one()
-        transport._force_close = mock.Mock()
-        with test_utils.disable_logger():
-            transport._read_ready()
-        transport._force_close.assert_called_with(err)
-
-    def test_read_ready_recv_retry(self):
-        self.sslsock.recv.side_effect = ssl.SSLWantReadError
-        transport = self._make_one()
-        transport._read_ready()
-        self.assertTrue(self.sslsock.recv.called)
-        self.assertFalse(self.protocol.data_received.called)
-
-        self.sslsock.recv.side_effect = BlockingIOError
-        transport._read_ready()
-        self.assertFalse(self.protocol.data_received.called)
-
-        self.sslsock.recv.side_effect = InterruptedError
-        transport._read_ready()
-        self.assertFalse(self.protocol.data_received.called)
-
-    def test_read_ready_recv_write(self):
-        self.loop._remove_reader = mock.Mock()
-        self.loop._add_writer = mock.Mock()
-        self.sslsock.recv.side_effect = ssl.SSLWantWriteError
-        transport = self._make_one()
-        transport._read_ready()
-        self.assertFalse(self.protocol.data_received.called)
-        self.assertTrue(transport._read_wants_write)
-
-        self.loop._remove_reader.assert_called_with(transport._sock_fd)
-        self.loop._add_writer.assert_called_with(
-            transport._sock_fd, transport._write_ready)
-
-    def test_read_ready_recv_exc(self):
-        err = self.sslsock.recv.side_effect = OSError()
-        transport = self._make_one()
-        transport._fatal_error = mock.Mock()
-        transport._read_ready()
-        transport._fatal_error.assert_called_with(
-                                   err,
-                                   'Fatal read error on SSL transport')
-
-    def test_write_ready_send(self):
-        self.sslsock.send.return_value = 4
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data'])
-        transport._write_ready()
-        self.assertEqual(list_to_buffer(), transport._buffer)
-        self.assertTrue(self.sslsock.send.called)
-
-    def test_write_ready_send_none(self):
-        self.sslsock.send.return_value = 0
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data1', b'data2'])
-        transport._write_ready()
-        self.assertTrue(self.sslsock.send.called)
-        self.assertEqual(list_to_buffer([b'data1data2']), transport._buffer)
-
-    def test_write_ready_send_partial(self):
-        self.sslsock.send.return_value = 2
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data1', b'data2'])
-        transport._write_ready()
-        self.assertTrue(self.sslsock.send.called)
-        self.assertEqual(list_to_buffer([b'ta1data2']), transport._buffer)
-
-    def test_write_ready_send_closing_partial(self):
-        self.sslsock.send.return_value = 2
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data1', b'data2'])
-        transport._write_ready()
-        self.assertTrue(self.sslsock.send.called)
-        self.assertFalse(self.sslsock.close.called)
-
-    def test_write_ready_send_closing(self):
-        self.sslsock.send.return_value = 4
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data'])
-        transport.close()
-        transport._write_ready()
-        self.protocol.connection_lost.assert_called_with(None)
-
-    def test_write_ready_send_closing_empty_buffer(self):
-        self.sslsock.send.return_value = 4
-        call_soon = self.loop.call_soon = mock.Mock()
-        transport = self._make_one()
-        transport._buffer = list_to_buffer()
-        transport.close()
-        transport._write_ready()
-        call_soon.assert_called_with(transport._call_connection_lost, None)
-
-    def test_write_ready_send_retry(self):
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data'])
-
-        self.sslsock.send.side_effect = ssl.SSLWantWriteError
-        transport._write_ready()
-        self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
-        self.sslsock.send.side_effect = BlockingIOError()
-        transport._write_ready()
-        self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
-    def test_write_ready_send_read(self):
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data'])
-
-        self.loop._remove_writer = mock.Mock()
-        self.sslsock.send.side_effect = ssl.SSLWantReadError
-        transport._write_ready()
-        self.assertFalse(self.protocol.data_received.called)
-        self.assertTrue(transport._write_wants_read)
-        self.loop._remove_writer.assert_called_with(transport._sock_fd)
-
-    def test_write_ready_send_exc(self):
-        err = self.sslsock.send.side_effect = OSError()
-
-        transport = self._make_one()
-        transport._buffer = list_to_buffer([b'data'])
-        transport._fatal_error = mock.Mock()
-        transport._write_ready()
-        transport._fatal_error.assert_called_with(
-                                   err,
-                                   'Fatal write error on SSL transport')
-        self.assertEqual(list_to_buffer(), transport._buffer)
-
-    def test_write_ready_read_wants_write(self):
-        self.loop._add_reader = mock.Mock()
-        self.sslsock.send.side_effect = BlockingIOError
-        transport = self._make_one()
-        transport._read_wants_write = True
-        transport._read_ready = mock.Mock()
-        transport._write_ready()
-
-        self.assertFalse(transport._read_wants_write)
-        transport._read_ready.assert_called_with()
-        self.loop._add_reader.assert_called_with(
-            transport._sock_fd, transport._read_ready)
-
-    def test_write_eof(self):
-        tr = self._make_one()
-        self.assertFalse(tr.can_write_eof())
-        self.assertRaises(NotImplementedError, tr.write_eof)
-
-    def check_close(self):
-        tr = self._make_one()
-        tr.close()
-
-        self.assertTrue(tr.is_closing())
-        self.assertEqual(1, self.loop.remove_reader_count[1])
-        self.assertEqual(tr._conn_lost, 1)
-
-        tr.close()
-        self.assertEqual(tr._conn_lost, 1)
-        self.assertEqual(1, self.loop.remove_reader_count[1])
-
-        test_utils.run_briefly(self.loop)
-
-    def test_close(self):
-        self.check_close()
-        self.assertTrue(self.protocol.connection_made.called)
-        self.assertTrue(self.protocol.connection_lost.called)
-
-    def test_close_not_connected(self):
-        self.sslsock.do_handshake.side_effect = ssl.SSLWantReadError
-        self.check_close()
-        self.assertFalse(self.protocol.connection_made.called)
-        self.assertFalse(self.protocol.connection_lost.called)
-
-    @unittest.skipIf(ssl is None, 'No SSL support')
-    def test_server_hostname(self):
-        self.ssl_transport(server_hostname='localhost')
-        self.sslcontext.wrap_socket.assert_called_with(
-            self.sock, do_handshake_on_connect=False, server_side=False,
-            server_hostname='localhost')
-
-
-class SelectorSslWithoutSslTransportTests(unittest.TestCase):
-
-    @mock.patch('asyncio.selector_events.ssl', None)
-    def test_ssl_transport_requires_ssl_module(self):
-        Mock = mock.Mock
-        with self.assertRaises(RuntimeError):
-            _SelectorSslTransport(Mock(), Mock(), Mock(), Mock())
-
-
 class SelectorDatagramTransportTests(test_utils.TestCase):
 
     def setUp(self):
diff --git a/Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst b/Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst
new file mode 100644 (file)
index 0000000..2d69539
--- /dev/null
@@ -0,0 +1 @@
+Drop legacy SSL transport from asyncio, ssl.MemoryBIO is always used anyway.