◐ Shell
clean mode source ↗

Issue 45097: "The loop argument is deprecated" reported when user code does not use it

With Python 3.9.7, "DeprecationWarning: The loop argument is deprecated" may be reported when user code does not use it. Here is an example:

import asyncio
import warnings

warnings.filterwarnings('error')

def crash():
    raise KeyboardInterrupt

async def main():
    asyncio.get_event_loop().call_soon(crash)
    await asyncio.sleep(5)

try:
    asyncio.run(main())
except KeyboardInterrupt:
    pass

On 3.9.6, no warning is reported, while results on 3.9.7 are

Traceback (most recent call last):
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
    self._run_once()
  File "/usr/lib/python3.9/asyncio/base_events.py", line 1890, in _run_once
    handle._run()
  File "/usr/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/home/yen/var/local/Computer/archlinux/community/python-anyio/trunk/cpython-3.9.7-regression.py", line 11, in crash
    raise KeyboardInterrupt
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/yen/var/local/Computer/archlinux/community/python-anyio/trunk/cpython-3.9.7-regression.py", line 18, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.9/asyncio/runners.py", line 47, in run
    _cancel_all_tasks(loop)
  File "/usr/lib/python3.9/asyncio/runners.py", line 64, in _cancel_all_tasks
    tasks.gather(*to_cancel, loop=loop, return_exceptions=True))
  File "/usr/lib/python3.9/asyncio/tasks.py", line 755, in gather
    warnings.warn("The loop argument is deprecated since Python 3.8, "
DeprecationWarning: The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.

As indicated by the traceback, the loop argument is used inside the asyncio library, not from user code. It has been an issue for some time, and the issue is exposed after changes for issue44815.

Credit: this example code is modified from an anyio test https://github.com/agronholm/anyio/blob/3.3.0/tests/test_taskgroups.py#L943. I noticed this issue when I was testing anyio against 3.9.7.
There are several calls of gather() and sleep() with the loop argument from the asyncio library. Since all deprecation warnings were silenced in tests it was unnoticed.

PR 28153 fixes the asyncio library, enables deprecation warnings in tests, fixes tests producing warnings and add several new tests for uncovered code. New tests will be ported to master later.