Skip to content

Commit 0726b73

Browse files
fix for tornado 6, backport of jupyter/notebook#4449
1 parent 4180bc8 commit 0726b73

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

.travis.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ before_install:
2727
fi
2828
2929
install:
30-
- pip install --pre .[test]
30+
- pip install --pre .[test] $EXTRA_PIP
3131
- wget https://github.com/jgm/pandoc/releases/download/1.19.1/pandoc-1.19.1-1-amd64.deb && sudo dpkg -i pandoc-1.19.1-1-amd64.deb
3232

3333

@@ -69,6 +69,10 @@ matrix:
6969
dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069)
7070
- python: 3.6
7171
env: GROUP=docs
72+
- python: 3.6 # extra test for older tornados
73+
env:
74+
- GROUP=python
75+
- EXTRA_PIP="tornado<5"
7276

7377
after_success:
7478
- codecov

jupyter_server/base/zmqhandlers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ def get(self, *args, **kwargs):
281281
# assign and yield in two step to avoid tornado 3 issues
282282
res = self.pre_get()
283283
yield gen.maybe_future(res)
284-
super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
284+
res = super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
285+
yield gen.maybe_future(res)
285286

286287
def initialize(self):
287288
self.log.debug("Initializing websocket connection %s", self.request.path)

jupyter_server/utils.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,30 @@
1212
import sys
1313
from distutils.version import LooseVersion
1414

15+
try:
16+
from inspect import isawaitable
17+
except ImportError:
18+
def isawaitable(f):
19+
"""If isawaitable is undefined, nothing is awaitable"""
20+
return False
21+
22+
try:
23+
from concurrent.futures import Future as ConcurrentFuture
24+
except ImportError:
25+
class ConcurrentFuture:
26+
"""If concurrent.futures isn't importable, nothing will be a c.f.Future"""
27+
pass
28+
1529
try:
1630
from urllib.parse import quote, unquote, urlparse
1731
except ImportError:
1832
from urllib import quote, unquote
1933
from urlparse import urlparse
2034

35+
# tornado.concurrent.Future is asyncio.Future
36+
# in tornado >=5 with Python 3
37+
from tornado.concurrent import Future as TornadoFuture
38+
from tornado import gen
2139
from ipython_genutils import py3compat
2240

2341
# UF_HIDDEN is a stat flag not defined in the stat module.
@@ -305,3 +323,32 @@ def _check_pid_posix(pid):
305323
check_pid = _check_pid_win32
306324
else:
307325
check_pid = _check_pid_posix
326+
327+
328+
def maybe_future(obj):
329+
"""Like tornado's gen.maybe_future
330+
but more compatible with asyncio for recent versions
331+
of tornado
332+
"""
333+
if isinstance(obj, TornadoFuture):
334+
return obj
335+
elif isawaitable(obj):
336+
return asyncio.ensure_future(obj)
337+
elif isinstance(obj, ConcurrentFuture):
338+
return asyncio.wrap_future(obj)
339+
else:
340+
# not awaitable, wrap scalar in future
341+
f = TornadoFuture()
342+
f.set_result(obj)
343+
return f
344+
345+
# monkeypatch tornado gen.maybe_future
346+
# on Python 3
347+
# TODO: remove monkeypatch after backporting smaller fix to 5.x
348+
try:
349+
import asyncio
350+
except ImportError:
351+
pass
352+
else:
353+
import tornado.gen
354+
tornado.gen.maybe_future = maybe_future

0 commit comments

Comments
 (0)