Description
Problem
Tornado's io_loop
is now a wrapper around the native asyncio
loop, and the tornado docs recommend using asyncio
and asyncio.run()
directly. In addition, there are plans to deprecate and remove asyncio.set_event_loop_policy
, meaning that the we would have to use the loop_factory
parameter that was added in Python 3.12.
We still want to use the SelectorEventLoop
on Windows when using tornado, because even though it supports ProactorEventLoop
as of tornado 6.1, it is less efficient, because it is using selectors in a thread.
Because ServerApp.io_loop
is a public property, we'll have to bump to 3.0, because it is used by at least jupyterlab
in a couple of places in tests (see below). We may also want to change it so that we start the event loop earlier, maybe in launch_instance
.
Proposed Solution
We should remove usages of tornadio.io_loop
up and down the stack, and add convenience function(s) in jupyter_core.utils
to handle starting an event loop for different versions of Python, and perhaps a replacement for PeriodicCallback
.
I will start by working on a PR to jupyter_client
that replaces usages of ZMQStream
.
Additional context
Known usages:
jupyter_server
:add_callback_from_signal
,add_callback
,start
, andstop
, all internal usages, butio_loop
is technically a public property.jupyter_client
: usesZMQStream
, which we'll need a replacement for. This seems to be the biggest remaining lift.ipykernel
: will be partially removed by Replace Tornado with AnyIO ipython/ipykernel#1079, but there are still usages injupyter_client/ioloop
.jupyterlab
:browser_check.py
andjupyterlab/tests/test_app.py
both useapp.io_loop
qtconsole
: we'll be able to remove the_init_asyncio_patch
shim once it depends on a version ofjupyter_client
that doesn't useZMQStream
inkernel_client.start_channels()
.