diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-01-14 23:04:21 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-01-14 23:04:21 (GMT) |
commit | 29ad0111bd8c7edd049c964c66cfb9e9114c99d2 (patch) | |
tree | 9fee6570ed8b11b78e9159153a7d241e1c212e21 | |
parent | b92626df5ca72d25236404a0a62cf47279c4e503 (diff) | |
download | cpython-29ad0111bd8c7edd049c964c66cfb9e9114c99d2.zip cpython-29ad0111bd8c7edd049c964c66cfb9e9114c99d2.tar.gz cpython-29ad0111bd8c7edd049c964c66cfb9e9114c99d2.tar.bz2 |
asyncio: sync with Tulip
* PipeHandle now uses None instead of -1 for a closed handle
* Sort imports in windows_utils.
* Fix test_events on Python older than 3.5. Skip SSL tests on the
ProactorEventLoop if ssl.MemoryIO is missing
* Fix BaseEventLoop._create_connection_transport(). Close the transport if the
creation of the transport (if the waiter) gets an exception.
* _ProactorBasePipeTransport now sets _sock to None when the transport is
closed.
* Fix BaseSubprocessTransport.close(). Ignore pipes for which the protocol is
not set yet (still equal to None).
* TestLoop.close() now calls the close() method of the parent class
(BaseEventLoop).
* Cleanup BaseSelectorEventLoop: create the protocol on a separated line for
readability and ease debugging.
* Fix BaseSubprocessTransport._kill_wait(). Set the _returncode attribute, so
close() doesn't try to terminate the process.
* Tests: explicitly close event loops and transports
* UNIX pipe transports: add closed/closing in repr(). Add "closed" or "closing"
state in the __repr__() method of _UnixReadPipeTransport and
_UnixWritePipeTransport classes.
-rw-r--r-- | Lib/asyncio/base_events.py | 7 | ||||
-rw-r--r-- | Lib/asyncio/base_subprocess.py | 4 | ||||
-rw-r--r-- | Lib/asyncio/proactor_events.py | 1 | ||||
-rw-r--r-- | Lib/asyncio/selector_events.py | 5 | ||||
-rw-r--r-- | Lib/asyncio/test_utils.py | 1 | ||||
-rw-r--r-- | Lib/asyncio/unix_events.py | 14 | ||||
-rw-r--r-- | Lib/asyncio/windows_utils.py | 10 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_base_events.py | 1 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_events.py | 22 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_futures.py | 1 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_selector_events.py | 1 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_unix_events.py | 1 |
12 files changed, 57 insertions, 11 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 35c8d74..5df5b83 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -634,7 +634,12 @@ class BaseEventLoop(events.AbstractEventLoop): else: transport = self._make_socket_transport(sock, protocol, waiter) - yield from waiter + try: + yield from waiter + except Exception as exc: + transport.close() + raise + return transport, protocol @coroutine diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 0787ad7..f5e7dfe 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -71,6 +71,8 @@ class BaseSubprocessTransport(transports.SubprocessTransport): def close(self): for proto in self._pipes.values(): + if proto is None: + continue proto.pipe.close() if self._returncode is None: self.terminate() @@ -119,7 +121,7 @@ class BaseSubprocessTransport(transports.SubprocessTransport): proc.kill() except ProcessLookupError: pass - proc.wait() + self._returncode = proc.wait() @coroutine def _post_init(self): diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 4716bb5..0ecb44e 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -111,6 +111,7 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin, if hasattr(self._sock, 'shutdown'): self._sock.shutdown(socket.SHUT_RDWR) self._sock.close() + self._sock = None server = self._server if server is not None: server._detach() diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 074a8df..4d3e5d9 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -182,13 +182,14 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): else: raise # The event loop will catch, log and ignore it. else: + protocol = protocol_factory() if sslcontext: self._make_ssl_transport( - conn, protocol_factory(), sslcontext, + conn, protocol, sslcontext, server_side=True, extra={'peername': addr}, server=server) else: self._make_socket_transport( - conn, protocol_factory(), extra={'peername': addr}, + conn, protocol , extra={'peername': addr}, server=server) # It's now up to the protocol to handle the connection. diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index 180bafa..6eedc58 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -307,6 +307,7 @@ class TestLoop(base_events.BaseEventLoop): self._time += advance def close(self): + super().close() if self._check_on_close: try: self._gen.send(0) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 1a4d418..14b4843 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -301,7 +301,12 @@ class _UnixReadPipeTransport(transports.ReadTransport): self._loop.call_soon(waiter._set_result_unless_cancelled, None) def __repr__(self): - info = [self.__class__.__name__, 'fd=%s' % self._fileno] + info = [self.__class__.__name__] + if self._pipe is None: + info.append('closed') + elif self._closing: + info.append('closing') + info.append('fd=%s' % self._fileno) if self._pipe is not None: polling = selector_events._test_selector_event( self._loop._selector, @@ -404,7 +409,12 @@ class _UnixWritePipeTransport(transports._FlowControlMixin, self._loop.call_soon(waiter._set_result_unless_cancelled, None) def __repr__(self): - info = [self.__class__.__name__, 'fd=%s' % self._fileno] + info = [self.__class__.__name__] + if self._pipe is None: + info.append('closed') + elif self._closing: + info.append('closing') + info.append('fd=%s' % self._fileno) if self._pipe is not None: polling = selector_events._test_selector_event( self._loop._selector, diff --git a/Lib/asyncio/windows_utils.py b/Lib/asyncio/windows_utils.py index b475812..e664296 100644 --- a/Lib/asyncio/windows_utils.py +++ b/Lib/asyncio/windows_utils.py @@ -7,13 +7,13 @@ import sys if sys.platform != 'win32': # pragma: no cover raise ImportError('win32 only') -import socket +import _winapi import itertools import msvcrt import os +import socket import subprocess import tempfile -import _winapi __all__ = ['socketpair', 'pipe', 'Popen', 'PIPE', 'PipeHandle'] @@ -136,7 +136,7 @@ class PipeHandle: self._handle = handle def __repr__(self): - if self._handle != -1: + if self._handle is not None: handle = 'handle=%r' % self._handle else: handle = 'closed' @@ -150,9 +150,9 @@ class PipeHandle: return self._handle def close(self, *, CloseHandle=_winapi.CloseHandle): - if self._handle != -1: + if self._handle is not None: CloseHandle(self._handle) - self._handle = -1 + self._handle = None __del__ = close diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 6bf7e79..bd6c0d8 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -409,6 +409,7 @@ class BaseEventLoopTests(test_utils.TestCase): def test_run_until_complete_loop(self): task = asyncio.Future(loop=self.loop) other_loop = self.new_test_loop() + self.addCleanup(other_loop.close) self.assertRaises(ValueError, other_loop.run_until_complete, task) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index a2c6dc9..a38c90e 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -25,6 +25,7 @@ import weakref import asyncio from asyncio import proactor_events from asyncio import selector_events +from asyncio import sslproto from asyncio import test_utils try: from test import support @@ -1585,6 +1586,7 @@ class SubprocessTestsMixin: self.assertTrue(all(f.done() for f in proto.disconnects.values())) self.assertEqual(proto.data[1].rstrip(b'\r\n'), b'Python') self.assertEqual(proto.data[2], b'') + transp.close() def test_subprocess_exitcode(self): connect = self.loop.subprocess_shell( @@ -1594,6 +1596,7 @@ class SubprocessTestsMixin: self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.completed) self.assertEqual(7, proto.returncode) + transp.close() def test_subprocess_close_after_finish(self): connect = self.loop.subprocess_shell( @@ -1621,6 +1624,7 @@ class SubprocessTestsMixin: transp.kill() self.loop.run_until_complete(proto.completed) self.check_killed(proto.returncode) + transp.close() def test_subprocess_terminate(self): prog = os.path.join(os.path.dirname(__file__), 'echo.py') @@ -1635,6 +1639,7 @@ class SubprocessTestsMixin: transp.terminate() self.loop.run_until_complete(proto.completed) self.check_terminated(proto.returncode) + transp.close() @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") def test_subprocess_send_signal(self): @@ -1650,6 +1655,7 @@ class SubprocessTestsMixin: transp.send_signal(signal.SIGHUP) self.loop.run_until_complete(proto.completed) self.assertEqual(-signal.SIGHUP, proto.returncode) + transp.close() def test_subprocess_stderr(self): prog = os.path.join(os.path.dirname(__file__), 'echo2.py') @@ -1784,6 +1790,22 @@ 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") diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index dac1e89..c8b6829 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -29,6 +29,7 @@ class FutureTests(test_utils.TestCase): def setUp(self): self.loop = self.new_test_loop() + self.addCleanup(self.loop.close) def test_initial_state(self): f = asyncio.Future(loop=self.loop) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 64c2e65..3e8392e 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1744,6 +1744,7 @@ class SelectorDatagramTransportTests(test_utils.TestCase): test_utils.MockPattern( 'Fatal error on transport\nprotocol:.*\ntransport:.*'), exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY)) + transport.close() if __name__ == '__main__': diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 4b825dc..5f4b024 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -598,6 +598,7 @@ class UnixWritePipeTransportTests(test_utils.TestCase): # This is a bit overspecified. :-( m_log.warning.assert_called_with( 'pipe closed by peer or os.write(pipe, data) raised exception.') + tr.close() @mock.patch('os.write') def test_write_close(self, m_write): |