Merge pull request #5047 from minrk/py38-tornado

workaround tornado py38 compatibility issue
This commit is contained in:
Thomas Kluyver 2019-11-24 18:21:20 +00:00 committed by GitHub
commit 1efa780a70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 3 deletions

View File

@ -1707,8 +1707,42 @@ class NotebookApp(JupyterApp):
pc = ioloop.PeriodicCallback(self.shutdown_no_activity, 60000)
pc.start()
def _init_asyncio_patch(self):
"""set default asyncio policy to be compatible with tornado
Tornado 6 (at least) is not compatible with the default
asyncio implementation on Windows
Pick the older SelectorEventLoopPolicy on Windows
if the known-incompatible default policy is in use.
do this as early as possible to make it a low priority and overrideable
ref: https://github.com/tornadoweb/tornado/issues/2608
FIXME: if/when tornado supports the defaults in asyncio,
remove and bump tornado requirement for py38
"""
if sys.platform.startswith("win") and sys.version_info >= (3, 8):
import asyncio
try:
from asyncio import (
WindowsProactorEventLoopPolicy,
WindowsSelectorEventLoopPolicy,
)
except ImportError:
pass
# not affected
else:
if type(asyncio.get_event_loop_policy()) is WindowsProactorEventLoopPolicy:
# WindowsProactorEventLoopPolicy is not compatible with tornado 6
# fallback to the pre-3.8 default of Selector
asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
@catch_config_error
def initialize(self, argv=None):
self._init_asyncio_patch()
super(NotebookApp, self).initialize(argv)
self.init_logging()
if self._dispatching:

View File

@ -140,9 +140,6 @@ class NotebookTestBase(TestCase):
started = Event()
def start_thread():
if 'asyncio' in sys.modules:
import asyncio
asyncio.set_event_loop(asyncio.new_event_loop())
app = cls.notebook = NotebookApp(
port=cls.port,
port_retries=0,
@ -156,6 +153,10 @@ class NotebookTestBase(TestCase):
allow_root=True,
token=cls.token,
)
if 'asyncio' in sys.modules:
app._init_asyncio_patch()
import asyncio
asyncio.set_event_loop(asyncio.new_event_loop())
# don't register signal handler during tests
app.init_signal = lambda : None
# clear log handlers and propagate to root for nose to capture it