]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.9] bpo-45097: Remove incorrect deprecation warnings in asyncio. (GH-28153)
authorSerhiy Storchaka <storchaka@gmail.com>
Sat, 4 Sep 2021 17:54:50 +0000 (20:54 +0300)
committerGitHub <noreply@github.com>
Sat, 4 Sep 2021 17:54:50 +0000 (20:54 +0300)
Deprecation warnings about the loop argument were incorrectly emitted
in cases when the loop argument was used inside the asyncio library,
not from user code.

Lib/asyncio/base_events.py
Lib/asyncio/runners.py
Lib/asyncio/subprocess.py
Lib/asyncio/tasks.py
Lib/asyncio/unix_events.py
Lib/test/test_asyncgen.py
Lib/test/test_asyncio/__init__.py
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_queues.py
Lib/test/test_asyncio/test_tasks.py
Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst [new file with mode: 0644]

index b2d446a51fedb50a75b7c72ba093799705e99257..bb2f99150b115aa4706cb2aa70672ab7b073ad89 100644 (file)
@@ -350,7 +350,7 @@ class Server(events.AbstractServer):
         self._start_serving()
         # Skip one loop iteration so that all 'loop.add_reader'
         # go through.
-        await tasks.sleep(0, loop=self._loop)
+        await tasks.sleep(0)
 
     async def serve_forever(self):
         if self._serving_forever_fut is not None:
@@ -539,7 +539,7 @@ class BaseEventLoop(events.AbstractEventLoop):
         closing_agens = list(self._asyncgens)
         self._asyncgens.clear()
 
-        results = await tasks.gather(
+        results = await tasks._gather(
             *[ag.aclose() for ag in closing_agens],
             return_exceptions=True,
             loop=self)
@@ -1457,7 +1457,7 @@ class BaseEventLoop(events.AbstractEventLoop):
             fs = [self._create_server_getaddrinfo(host, port, family=family,
                                                   flags=flags)
                   for host in hosts]
-            infos = await tasks.gather(*fs, loop=self)
+            infos = await tasks._gather(*fs, loop=self)
             infos = set(itertools.chain.from_iterable(infos))
 
             completed = False
@@ -1515,7 +1515,7 @@ class BaseEventLoop(events.AbstractEventLoop):
             server._start_serving()
             # Skip one loop iteration so that all 'loop.add_reader'
             # go through.
-            await tasks.sleep(0, loop=self)
+            await tasks.sleep(0)
 
         if self._debug:
             logger.info("%r is serving", server)
index 268635d68fb0c0ec00a828a391c891d077f74c14..6920acba381525c3d012de3ec846d7c68a031248 100644 (file)
@@ -61,7 +61,7 @@ def _cancel_all_tasks(loop):
         task.cancel()
 
     loop.run_until_complete(
-        tasks.gather(*to_cancel, loop=loop, return_exceptions=True))
+        tasks._gather(*to_cancel, loop=loop, return_exceptions=True))
 
     for task in to_cancel:
         if task.cancelled():
index c9506b158302b5e8027a636fdb7c9ca9c965b938..820304eccaf442a318edd294f4078d6442ef0835 100644 (file)
@@ -193,8 +193,8 @@ class Process:
             stderr = self._read_stream(2)
         else:
             stderr = self._noop()
-        stdin, stdout, stderr = await tasks.gather(stdin, stdout, stderr,
-                                                   loop=self._loop)
+        stdin, stdout, stderr = await tasks._gather(stdin, stdout, stderr,
+                                                    loop=self._loop)
         await self.wait()
         return (stdout, stderr)
 
index d7e0575ebd7fbb8a9a494a48c63857ac7dadf42b..22ed3289edf3cd521ff27b418470fc783c9a8c0c 100644 (file)
@@ -580,15 +580,16 @@ def as_completed(fs, *, loop=None, timeout=None):
     if futures.isfuture(fs) or coroutines.iscoroutine(fs):
         raise TypeError(f"expect an iterable of futures, not {type(fs).__name__}")
 
+    if loop is not None:
+        warnings.warn("The loop argument is deprecated since Python 3.8, "
+                      "and scheduled for removal in Python 3.10.",
+                      DeprecationWarning, stacklevel=2)
+
     from .queues import Queue  # Import here to avoid circular import problem.
     done = Queue(loop=loop)
 
     if loop is None:
         loop = events.get_event_loop()
-    else:
-        warnings.warn("The loop argument is deprecated since Python 3.8, "
-                      "and scheduled for removal in Python 3.10.",
-                      DeprecationWarning, stacklevel=2)
     todo = {ensure_future(f, loop=loop) for f in set(fs)}
     timeout_handle = None
 
@@ -756,6 +757,10 @@ def gather(*coros_or_futures, loop=None, return_exceptions=False):
                       "and scheduled for removal in Python 3.10.",
                       DeprecationWarning, stacklevel=2)
 
+    return _gather(*coros_or_futures, loop=loop, return_exceptions=return_exceptions)
+
+
+def _gather(*coros_or_futures, loop=None, return_exceptions=False):
     if not coros_or_futures:
         if loop is None:
             loop = events.get_event_loop()
index 3efa6698b89ced4673687957be769602c20c0af0..56fcc084e311f4d754536f1179c60548fab15525 100644 (file)
@@ -323,7 +323,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
             server._start_serving()
             # Skip one loop iteration so that all 'loop.add_reader'
             # go through.
-            await tasks.sleep(0, loop=self)
+            await tasks.sleep(0)
 
         return server
 
index 8d2ad2233ae1f5f5ddf16147ade310a0f47364fd..15997380861d0688e37db3c639e7518bb01cdfdf 100644 (file)
@@ -1077,6 +1077,84 @@ class AsyncGenAsyncioTest(unittest.TestCase):
 
         self.assertEqual(finalized, 2)
 
+    def test_async_gen_asyncio_shutdown_02(self):
+        messages = []
+
+        def exception_handler(loop, context):
+            messages.append(context)
+
+        async def async_iterate():
+            yield 1
+            yield 2
+
+        it = async_iterate()
+        async def main():
+            loop = asyncio.get_running_loop()
+            loop.set_exception_handler(exception_handler)
+
+            async for i in it:
+                break
+
+        asyncio.run(main())
+
+        self.assertEqual(messages, [])
+
+    def test_async_gen_asyncio_shutdown_exception_01(self):
+        messages = []
+
+        def exception_handler(loop, context):
+            messages.append(context)
+
+        async def async_iterate():
+            try:
+                yield 1
+                yield 2
+            finally:
+                1/0
+
+        it = async_iterate()
+        async def main():
+            loop = asyncio.get_running_loop()
+            loop.set_exception_handler(exception_handler)
+
+            async for i in it:
+                break
+
+        asyncio.run(main())
+
+        message, = messages
+        self.assertEqual(message['asyncgen'], it)
+        self.assertIsInstance(message['exception'], ZeroDivisionError)
+        self.assertIn('an error occurred during closing of asynchronous generator',
+                      message['message'])
+
+    def test_async_gen_asyncio_shutdown_exception_02(self):
+        messages = []
+
+        def exception_handler(loop, context):
+            messages.append(context)
+
+        async def async_iterate():
+            try:
+                yield 1
+                yield 2
+            finally:
+                1/0
+
+        async def main():
+            loop = asyncio.get_running_loop()
+            loop.set_exception_handler(exception_handler)
+
+            async for i in async_iterate():
+                break
+
+        asyncio.run(main())
+
+        message, = messages
+        self.assertIsInstance(message['exception'], ZeroDivisionError)
+        self.assertIn('unhandled exception during asyncio.run() shutdown',
+                      message['message'])
+
     def test_async_gen_expression_01(self):
         async def arange(n):
             for i in range(n):
index 4a7a868980d88be11d6d1b8e75fb0f7ababb2c02..5535b88cff0187c855a34a35717699ae6ef75299 100644 (file)
@@ -1,38 +1,10 @@
 import os
 from test import support
-import unittest
 
 # Skip tests if we don't have concurrent.futures.
 support.import_module('concurrent.futures')
 
 
-def load_tests(loader, _, pattern):
+def load_tests(*args):
     pkg_dir = os.path.dirname(__file__)
-    suite = AsyncioTestSuite()
-    return support.load_package_tests(pkg_dir, loader, suite, pattern)
-
-
-class AsyncioTestSuite(unittest.TestSuite):
-    """A custom test suite that also runs setup/teardown for the whole package.
-
-    Normally unittest only runs setUpModule() and tearDownModule() within each
-    test module part of the test suite. Copying those functions to each file
-    would be tedious, let's run this once and for all.
-    """
-    def run(self, result, debug=False):
-        ignore = support.ignore_deprecations_from
-        tokens = {
-            ignore("asyncio.base_events", like=r".*loop argument.*"),
-            ignore("asyncio.unix_events", like=r".*loop argument.*"),
-            ignore("asyncio.futures", like=r".*loop argument.*"),
-            ignore("asyncio.runners", like=r".*loop argument.*"),
-            ignore("asyncio.subprocess", like=r".*loop argument.*"),
-            ignore("asyncio.tasks", like=r".*loop argument.*"),
-            ignore("test.test_asyncio.test_events", like=r".*loop argument.*"),
-            ignore("test.test_asyncio.test_queues", like=r".*loop argument.*"),
-            ignore("test.test_asyncio.test_tasks", like=r".*loop argument.*"),
-        }
-        try:
-            super().run(result, debug=debug)
-        finally:
-            support.clear_ignored_deprecations(*tokens)
+    return support.load_package_tests(pkg_dir, *args)
index 7114c2f0c71daa0135cb8e3319946e9edb13a27e..72189bfd38e2b14d61d77bc2b30ac9e39689dd73 100644 (file)
@@ -205,8 +205,8 @@ class MySubprocessProtocol(asyncio.SubprocessProtocol):
         self.disconnects = {fd: loop.create_future() for fd in range(3)}
         self.data = {1: b'', 2: b''}
         self.returncode = None
-        self.got_data = {1: asyncio.Event(loop=loop),
-                         2: asyncio.Event(loop=loop)}
+        self.got_data = {1: asyncio.Event(),
+                         2: asyncio.Event()}
 
     def connection_made(self, transport):
         self.transport = transport
@@ -1736,20 +1736,19 @@ class SubprocessTestsMixin:
         connect = self.loop.subprocess_exec(
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog)
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
-            self.assertEqual('CONNECTED', proto.state)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
+        self.assertEqual('CONNECTED', proto.state)
 
-            stdin = transp.get_pipe_transport(0)
-            stdin.write(b'Python The Winner')
-            self.loop.run_until_complete(proto.got_data[1].wait())
-            with test_utils.disable_logger():
-                transp.close()
-            self.loop.run_until_complete(proto.completed)
-            self.check_killed(proto.returncode)
-            self.assertEqual(b'Python The Winner', proto.data[1])
+        stdin = transp.get_pipe_transport(0)
+        stdin.write(b'Python The Winner')
+        self.loop.run_until_complete(proto.got_data[1].wait())
+        with test_utils.disable_logger():
+            transp.close()
+        self.loop.run_until_complete(proto.completed)
+        self.check_killed(proto.returncode)
+        self.assertEqual(b'Python The Winner', proto.data[1])
 
     def test_subprocess_interactive(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo.py')
@@ -1758,51 +1757,48 @@ class SubprocessTestsMixin:
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog)
 
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
-            self.assertEqual('CONNECTED', proto.state)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
+        self.assertEqual('CONNECTED', proto.state)
 
-            stdin = transp.get_pipe_transport(0)
-            stdin.write(b'Python ')
-            self.loop.run_until_complete(proto.got_data[1].wait())
-            proto.got_data[1].clear()
-            self.assertEqual(b'Python ', proto.data[1])
+        stdin = transp.get_pipe_transport(0)
+        stdin.write(b'Python ')
+        self.loop.run_until_complete(proto.got_data[1].wait())
+        proto.got_data[1].clear()
+        self.assertEqual(b'Python ', proto.data[1])
 
-            stdin.write(b'The Winner')
-            self.loop.run_until_complete(proto.got_data[1].wait())
-            self.assertEqual(b'Python The Winner', proto.data[1])
+        stdin.write(b'The Winner')
+        self.loop.run_until_complete(proto.got_data[1].wait())
+        self.assertEqual(b'Python The Winner', proto.data[1])
 
-            with test_utils.disable_logger():
-                transp.close()
-            self.loop.run_until_complete(proto.completed)
-            self.check_killed(proto.returncode)
+        with test_utils.disable_logger():
+            transp.close()
+        self.loop.run_until_complete(proto.completed)
+        self.check_killed(proto.returncode)
 
     def test_subprocess_shell(self):
-        with self.assertWarns(DeprecationWarning):
-            connect = self.loop.subprocess_shell(
-                            functools.partial(MySubprocessProtocol, self.loop),
-                            'echo Python')
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
+        connect = self.loop.subprocess_shell(
+                        functools.partial(MySubprocessProtocol, self.loop),
+                        'echo Python')
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
 
-            transp.get_pipe_transport(0).close()
-            self.loop.run_until_complete(proto.completed)
-            self.assertEqual(0, proto.returncode)
-            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()
+        transp.get_pipe_transport(0).close()
+        self.loop.run_until_complete(proto.completed)
+        self.assertEqual(0, proto.returncode)
+        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(
                         functools.partial(MySubprocessProtocol, self.loop),
                         'exit 7', stdin=None, stdout=None, stderr=None)
 
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
+        transp, proto = self.loop.run_until_complete(connect)
         self.assertIsInstance(proto, MySubprocessProtocol)
         self.loop.run_until_complete(proto.completed)
         self.assertEqual(7, proto.returncode)
@@ -1812,8 +1808,7 @@ class SubprocessTestsMixin:
         connect = self.loop.subprocess_shell(
                         functools.partial(MySubprocessProtocol, self.loop),
                         'exit 7', stdin=None, stdout=None, stderr=None)
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
+        transp, proto = self.loop.run_until_complete(connect)
         self.assertIsInstance(proto, MySubprocessProtocol)
         self.assertIsNone(transp.get_pipe_transport(0))
         self.assertIsNone(transp.get_pipe_transport(1))
@@ -1829,15 +1824,14 @@ class SubprocessTestsMixin:
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog)
 
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
 
-            transp.kill()
-            self.loop.run_until_complete(proto.completed)
-            self.check_killed(proto.returncode)
-            transp.close()
+        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')
@@ -1846,15 +1840,14 @@ class SubprocessTestsMixin:
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog)
 
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
 
-            transp.terminate()
-            self.loop.run_until_complete(proto.completed)
-            self.check_terminated(proto.returncode)
-            transp.close()
+        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):
@@ -1869,15 +1862,14 @@ class SubprocessTestsMixin:
                             functools.partial(MySubprocessProtocol, self.loop),
                             sys.executable, prog)
 
-            with self.assertWarns(DeprecationWarning):
-                transp, proto = self.loop.run_until_complete(connect)
-                self.assertIsInstance(proto, MySubprocessProtocol)
-                self.loop.run_until_complete(proto.connected)
+            transp, proto = self.loop.run_until_complete(connect)
+            self.assertIsInstance(proto, MySubprocessProtocol)
+            self.loop.run_until_complete(proto.connected)
 
-                transp.send_signal(signal.SIGHUP)
-                self.loop.run_until_complete(proto.completed)
-                self.assertEqual(-signal.SIGHUP, proto.returncode)
-                transp.close()
+            transp.send_signal(signal.SIGHUP)
+            self.loop.run_until_complete(proto.completed)
+            self.assertEqual(-signal.SIGHUP, proto.returncode)
+            transp.close()
         finally:
             signal.signal(signal.SIGHUP, old_handler)
 
@@ -1888,20 +1880,19 @@ class SubprocessTestsMixin:
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog)
 
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
 
-            stdin = transp.get_pipe_transport(0)
-            stdin.write(b'test')
+        stdin = transp.get_pipe_transport(0)
+        stdin.write(b'test')
 
-            self.loop.run_until_complete(proto.completed)
+        self.loop.run_until_complete(proto.completed)
 
-            transp.close()
-            self.assertEqual(b'OUT:test', proto.data[1])
-            self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2])
-            self.assertEqual(0, proto.returncode)
+        transp.close()
+        self.assertEqual(b'OUT:test', proto.data[1])
+        self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2])
+        self.assertEqual(0, proto.returncode)
 
     def test_subprocess_stderr_redirect_to_stdout(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo2.py')
@@ -1910,23 +1901,22 @@ class SubprocessTestsMixin:
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog, stderr=subprocess.STDOUT)
 
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
 
-            stdin = transp.get_pipe_transport(0)
-            self.assertIsNotNone(transp.get_pipe_transport(1))
-            self.assertIsNone(transp.get_pipe_transport(2))
+        stdin = transp.get_pipe_transport(0)
+        self.assertIsNotNone(transp.get_pipe_transport(1))
+        self.assertIsNone(transp.get_pipe_transport(2))
 
-            stdin.write(b'test')
-            self.loop.run_until_complete(proto.completed)
-            self.assertTrue(proto.data[1].startswith(b'OUT:testERR:test'),
-                            proto.data[1])
-            self.assertEqual(b'', proto.data[2])
+        stdin.write(b'test')
+        self.loop.run_until_complete(proto.completed)
+        self.assertTrue(proto.data[1].startswith(b'OUT:testERR:test'),
+                        proto.data[1])
+        self.assertEqual(b'', proto.data[2])
 
-            transp.close()
-            self.assertEqual(0, proto.returncode)
+        transp.close()
+        self.assertEqual(0, proto.returncode)
 
     def test_subprocess_close_client_stream(self):
         prog = os.path.join(os.path.dirname(__file__), 'echo3.py')
@@ -1934,33 +1924,32 @@ class SubprocessTestsMixin:
         connect = self.loop.subprocess_exec(
                         functools.partial(MySubprocessProtocol, self.loop),
                         sys.executable, prog)
-        with self.assertWarns(DeprecationWarning):
-            transp, proto = self.loop.run_until_complete(connect)
-            self.assertIsInstance(proto, MySubprocessProtocol)
-            self.loop.run_until_complete(proto.connected)
+        transp, proto = self.loop.run_until_complete(connect)
+        self.assertIsInstance(proto, MySubprocessProtocol)
+        self.loop.run_until_complete(proto.connected)
 
-            stdin = transp.get_pipe_transport(0)
-            stdout = transp.get_pipe_transport(1)
-            stdin.write(b'test')
-            self.loop.run_until_complete(proto.got_data[1].wait())
-            self.assertEqual(b'OUT:test', proto.data[1])
+        stdin = transp.get_pipe_transport(0)
+        stdout = transp.get_pipe_transport(1)
+        stdin.write(b'test')
+        self.loop.run_until_complete(proto.got_data[1].wait())
+        self.assertEqual(b'OUT:test', proto.data[1])
 
-            stdout.close()
-            self.loop.run_until_complete(proto.disconnects[1])
-            stdin.write(b'xxx')
-            self.loop.run_until_complete(proto.got_data[2].wait())
-            if sys.platform != 'win32':
-                self.assertEqual(b'ERR:BrokenPipeError', proto.data[2])
-            else:
-                # After closing the read-end of a pipe, writing to the
-                # write-end using os.write() fails with errno==EINVAL and
-                # GetLastError()==ERROR_INVALID_NAME on Windows!?!  (Using
-                # WriteFile() we get ERROR_BROKEN_PIPE as expected.)
-                self.assertEqual(b'ERR:OSError', proto.data[2])
-            with test_utils.disable_logger():
-                transp.close()
-            self.loop.run_until_complete(proto.completed)
-            self.check_killed(proto.returncode)
+        stdout.close()
+        self.loop.run_until_complete(proto.disconnects[1])
+        stdin.write(b'xxx')
+        self.loop.run_until_complete(proto.got_data[2].wait())
+        if sys.platform != 'win32':
+            self.assertEqual(b'ERR:BrokenPipeError', proto.data[2])
+        else:
+            # After closing the read-end of a pipe, writing to the
+            # write-end using os.write() fails with errno==EINVAL and
+            # GetLastError()==ERROR_INVALID_NAME on Windows!?!  (Using
+            # WriteFile() we get ERROR_BROKEN_PIPE as expected.)
+            self.assertEqual(b'ERR:OSError', proto.data[2])
+        with test_utils.disable_logger():
+            transp.close()
+        self.loop.run_until_complete(proto.completed)
+        self.check_killed(proto.returncode)
 
     def test_subprocess_wait_no_same_group(self):
         # start the new process in a new session
index 5c9aaa82c311a54ffeb7f2b5da23ba819a609129..81e888fbce6dbba13a181b912824339c4d1ed1b9 100644 (file)
@@ -301,11 +301,12 @@ class QueueGetTests(_QueueTestBase):
         with self.assertWarns(DeprecationWarning):
             q = asyncio.Queue(queue_size, loop=self.loop)
 
-        self.loop.run_until_complete(
-            asyncio.gather(producer(q, producer_num_items),
-                           consumer(q, producer_num_items),
-                           loop=self.loop),
-            )
+        with self.assertWarns(DeprecationWarning):
+            self.loop.run_until_complete(
+                asyncio.gather(producer(q, producer_num_items),
+                               consumer(q, producer_num_items),
+                               loop=self.loop),
+                )
 
     def test_cancelled_getters_not_being_held_in_self_getters(self):
         def a_generator():
@@ -555,8 +556,9 @@ class QueuePutTests(_QueueTestBase):
         t1 = putter(1)
         t2 = putter(2)
         t3 = putter(3)
-        self.loop.run_until_complete(
-            asyncio.gather(getter(), t0, t1, t2, t3, loop=self.loop))
+        with self.assertWarns(DeprecationWarning):
+            self.loop.run_until_complete(
+                asyncio.gather(getter(), t0, t1, t2, t3, loop=self.loop))
 
     def test_cancelled_puts_not_being_held_in_self_putters(self):
         def a_generator():
index d2d78033aa481a08a605d7eee78433cfdac3655b..5e14b62be1845b85f0b440c705ef3bc9df00c0cb 100644 (file)
@@ -1606,8 +1606,9 @@ class BaseTaskTests:
             for f in asyncio.as_completed([b, c, a], loop=loop):
                 values.append(await f)
             return values
-        with self.assertWarns(DeprecationWarning):
+        with self.assertWarns(DeprecationWarning) as w:
             res = loop.run_until_complete(self.new_task(loop, foo()))
+        self.assertEqual(w.warnings[0].filename, __file__)
         self.assertAlmostEqual(0.15, loop.time())
         self.assertTrue('a' in res[:2])
         self.assertTrue('b' in res[:2])
@@ -3348,7 +3349,8 @@ class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
         with self.assertRaises(ValueError):
             asyncio.gather(fut1, fut2)
         with self.assertRaises(ValueError):
-            asyncio.gather(fut1, loop=self.other_loop)
+            with self.assertWarns(DeprecationWarning):
+                asyncio.gather(fut1, loop=self.other_loop)
 
     def test_constructor_homogenous_futures(self):
         children = [self.other_loop.create_future() for i in range(3)]
@@ -3356,7 +3358,8 @@ class FutureGatherTests(GatherTestsBase, test_utils.TestCase):
         self.assertIs(fut._loop, self.other_loop)
         self._run_loop(self.other_loop)
         self.assertFalse(fut.done())
-        fut = asyncio.gather(*children, loop=self.other_loop)
+        with self.assertWarns(DeprecationWarning):
+            fut = asyncio.gather(*children, loop=self.other_loop)
         self.assertIs(fut._loop, self.other_loop)
         self._run_loop(self.other_loop)
         self.assertFalse(fut.done())
@@ -3429,7 +3432,8 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
         self.set_event_loop(self.other_loop, cleanup=False)
         gen3 = coro()
         gen4 = coro()
-        fut2 = asyncio.gather(gen3, gen4, loop=self.other_loop)
+        with self.assertWarns(DeprecationWarning):
+            fut2 = asyncio.gather(gen3, gen4, loop=self.other_loop)
         self.assertIs(fut2._loop, self.other_loop)
         self.other_loop.run_until_complete(fut2)
 
@@ -3439,7 +3443,8 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
             def coro(s):
                 return s
         c = coro('abc')
-        fut = asyncio.gather(c, c, coro('def'), c, loop=self.one_loop)
+        with self.assertWarns(DeprecationWarning):
+            fut = asyncio.gather(c, c, coro('def'), c, loop=self.one_loop)
         self._run_loop(self.one_loop)
         self.assertEqual(fut.result(), ['abc', 'abc', 'def', 'abc'])
 
@@ -3459,7 +3464,7 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
 
         async def outer():
             nonlocal proof, gatherer
-            gatherer = asyncio.gather(child1, child2, loop=self.one_loop)
+            gatherer = asyncio.gather(child1, child2)
             await gatherer
             proof += 100
 
@@ -3486,7 +3491,7 @@ class CoroutineGatherTests(GatherTestsBase, test_utils.TestCase):
         b = self.one_loop.create_future()
 
         async def outer():
-            await asyncio.gather(inner(a), inner(b), loop=self.one_loop)
+            await asyncio.gather(inner(a), inner(b))
 
         f = asyncio.ensure_future(outer(), loop=self.one_loop)
         test_utils.run_briefly(self.one_loop)
@@ -3705,7 +3710,7 @@ class CompatibilityTests(test_utils.TestCase):
                 return 'ok2'
 
         async def inner():
-            return await asyncio.gather(coro1(), coro2(), loop=self.loop)
+            return await asyncio.gather(coro1(), coro2())
 
         result = self.loop.run_until_complete(inner())
         self.assertEqual(['ok1', 'ok2'], result)
diff --git a/Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst b/Misc/NEWS.d/next/Library/2021-09-04-13-10-25.bpo-45097.5J4IC-.rst
new file mode 100644 (file)
index 0000000..1788300
--- /dev/null
@@ -0,0 +1,2 @@
+Remove deprecation warnings about the loop argument in :mod:`asyncio`
+incorrectly emitted in cases when the user does not pass the loop argument.