Skip to content

Commit 3574e21

Browse files
minrkZsailer
authored andcommitted
require Python 3.5
3.4 doesn't have isawaitable remove unsupported combinations from test matrix
1 parent d95ccaa commit 3574e21

File tree

7 files changed

+51
-51
lines changed

7 files changed

+51
-51
lines changed

.travis.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ matrix:
6868
dist: xenial # required for Python >= 3.7 (travis-ci/travis-ci#9069)
6969
- python: 3.6
7070
env: GROUP=docs
71-
- python: 3.6
72-
env:
73-
- GROUP=python
74-
- EXTRA_PIP="tornado<5"
7571

7672
after_success:
7773
- codecov

jupyter_server/files/handlers.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,11 @@
66
import mimetypes
77
import json
88
from base64 import decodebytes
9-
10-
from base64 import decodebytes
11-
129
from tornado import gen, web
13-
1410
from jupyter_server.base.handlers import JupyterHandler
1511
from jupyter_server.utils import maybe_future
1612

1713

18-
1914
class FilesHandler(JupyterHandler):
2015
"""serve files via ContentsManager
2116

jupyter_server/services/kernelspecs/handlers.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import os
1212
pjoin = os.path.join
1313

14-
from tornado import web
14+
from tornado import web, gen
1515

1616
from ...base.handlers import APIHandler
1717
from ...utils import maybe_future, url_path_join, url_unescape
@@ -49,6 +49,7 @@ def kernelspec_model(handler, name, spec_dict, resource_dir):
4949
class MainKernelSpecHandler(APIHandler):
5050

5151
@web.authenticated
52+
@gen.coroutine
5253
def get(self):
5354
ksm = self.kernel_spec_manager
5455
km = self.kernel_manager
@@ -71,6 +72,7 @@ def get(self):
7172
class KernelSpecHandler(APIHandler):
7273

7374
@web.authenticated
75+
@gen.coroutine
7476
def get(self, kernel_name):
7577
ksm = self.kernel_spec_manager
7678
kernel_name = url_unescape(kernel_name)

jupyter_server/services/sessions/sessionmanager.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ class SessionManager(LoggingConfigurable):
2424

2525
kernel_manager = Instance('jupyter_server.services.kernels.kernelmanager.MappingKernelManager')
2626
contents_manager = Instance('jupyter_server.services.contents.manager.ContentsManager')
27-
27+
2828
# Session database initialized below
2929
_cursor = None
3030
_connection = None
3131
_columns = {'session_id', 'path', 'name', 'type', 'kernel_id'}
32-
32+
3333
@property
3434
def cursor(self):
3535
"""Start a cursor and create a database called 'session'"""
3636
if self._cursor is None:
3737
self._cursor = self.connection.cursor()
38-
self._cursor.execute("""CREATE TABLE session
38+
self._cursor.execute("""CREATE TABLE session
3939
(session_id, path, name, type, kernel_id)""")
4040
return self._cursor
4141

@@ -46,7 +46,7 @@ def connection(self):
4646
self._connection = sqlite3.connect(':memory:')
4747
self._connection.row_factory = sqlite3.Row
4848
return self._connection
49-
49+
5050
def close(self):
5151
"""Close the sqlite connection"""
5252
if self._cursor is not None:
@@ -57,13 +57,13 @@ def __del__(self):
5757
"""Close connection once SessionManager closes"""
5858
self.close()
5959

60+
@gen.coroutine
6061
def session_exists(self, path):
6162
"""Check to see if the session of a given name exists"""
63+
exists = False
6264
self.cursor.execute("SELECT * FROM session WHERE path=?", (path,))
6365
row = self.cursor.fetchone()
64-
if row is None:
65-
return False
66-
else:
66+
if row is not None:
6767
# Note, although we found a row for the session, the associated kernel may have
6868
# been culled or died unexpectedly. If that's the case, we should delete the
6969
# row, thereby terminating the session. This can be done via a call to
@@ -103,13 +103,14 @@ def start_kernel_for_session(self, session_id, path, name, type, kernel_name):
103103
# py2-compat
104104
raise gen.Return(kernel_id)
105105

106+
@gen.coroutine
106107
def save_session(self, session_id, path=None, name=None, type=None, kernel_id=None):
107108
"""Saves the items for the session with the given session_id
108-
109+
109110
Given a session_id (and any other of the arguments), this method
110111
creates a row in the sqlite session database that holds the information
111112
for a session.
112-
113+
113114
Parameters
114115
----------
115116
session_id : str
@@ -122,7 +123,7 @@ def save_session(self, session_id, path=None, name=None, type=None, kernel_id=No
122123
the type of the session
123124
kernel_id : str
124125
a uuid for the kernel associated with this session
125-
126+
126127
Returns
127128
-------
128129
model : dict
@@ -134,9 +135,10 @@ def save_session(self, session_id, path=None, name=None, type=None, kernel_id=No
134135
result = yield maybe_future(self.get_session(session_id=session_id))
135136
raise gen.Return(result)
136137

138+
@gen.coroutine
137139
def get_session(self, **kwargs):
138140
"""Returns the model for a particular session.
139-
141+
140142
Takes a keyword argument and searches for the value in the session
141143
database, then returns the rest of the session's info.
142144
@@ -149,7 +151,7 @@ def get_session(self, **kwargs):
149151
Returns
150152
-------
151153
model : dict
152-
returns a dictionary that includes all the information from the
154+
returns a dictionary that includes all the information from the
153155
session described by the kwarg.
154156
"""
155157
if not kwargs:
@@ -180,19 +182,20 @@ def get_session(self, **kwargs):
180182
model = yield maybe_future(self.row_to_model(row))
181183
raise gen.Return(model)
182184

185+
@gen.coroutine
183186
def update_session(self, session_id, **kwargs):
184187
"""Updates the values in the session database.
185-
188+
186189
Changes the values of the session with the given session_id
187-
with the values from the keyword arguments.
188-
190+
with the values from the keyword arguments.
191+
189192
Parameters
190193
----------
191194
session_id : str
192195
a uuid that identifies a session in the sqlite3 database
193196
**kwargs : str
194197
the key must correspond to a column title in session database,
195-
and the value replaces the current value in the session
198+
and the value replaces the current value in the session
196199
with session_id.
197200
"""
198201
yield maybe_future(self.get_session(session_id=session_id))
@@ -209,6 +212,11 @@ def update_session(self, session_id, **kwargs):
209212
query = "UPDATE session SET %s WHERE session_id=?" % (', '.join(sets))
210213
self.cursor.execute(query, list(kwargs.values()) + [session_id])
211214

215+
def kernel_culled(self, kernel_id):
216+
"""Checks if the kernel is still considered alive and returns true if its not found. """
217+
return kernel_id not in self.kernel_manager
218+
219+
@gen.coroutine
212220
def row_to_model(self, row, tolerate_culled=False):
213221
"""Takes sqlite database session row and turns it into a dictionary"""
214222
kernel_culled = yield maybe_future(self.kernel_culled(row['kernel_id']))
@@ -227,7 +235,7 @@ def row_to_model(self, row, tolerate_culled=False):
227235
format(kernel_id=row['kernel_id'],session_id=row['session_id'])
228236
if tolerate_culled:
229237
self.log.warning(msg + " Continuing...")
230-
return None
238+
raise gen.Return(None)
231239
raise KeyError(msg)
232240

233241
kernel_model = yield maybe_future(self.kernel_manager.kernel_model(row['kernel_id']))
@@ -236,13 +244,14 @@ def row_to_model(self, row, tolerate_culled=False):
236244
'path': row['path'],
237245
'name': row['name'],
238246
'type': row['type'],
239-
'kernel': self.kernel_manager.kernel_model(row['kernel_id'])
247+
'kernel': kernel_model
240248
}
241249
if row['type'] == 'notebook':
242250
# Provide the deprecated API.
243251
model['notebook'] = {'path': row['path'], 'name': row['name']}
244-
return model
252+
raise gen.Return(model)
245253

254+
@gen.coroutine
246255
def list_sessions(self):
247256
"""Returns a list of dictionaries containing all the information from
248257
the session database"""
@@ -256,7 +265,7 @@ def list_sessions(self):
256265
result.append(model)
257266
except KeyError:
258267
pass
259-
return result
268+
raise gen.Return(result)
260269

261270
@gen.coroutine
262271
def delete_session(self, session_id):

jupyter_server/services/sessions/tests/test_sessionmanager.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,22 @@
1111
from jupyter_server.services.contents.manager import ContentsManager
1212
from jupyter_server._tz import utcnow, isoformat
1313

14-
1514
class DummyKernel(object):
1615
def __init__(self, kernel_name='python'):
1716
self.kernel_name = kernel_name
1817

1918
dummy_date = utcnow()
2019
dummy_date_s = isoformat(dummy_date)
2120

22-
2321
class DummyMKM(MappingKernelManager):
2422
"""MappingKernelManager interface that doesn't start kernels, for testing"""
25-
2623
def __init__(self, *args, **kwargs):
2724
super(DummyMKM, self).__init__(*args, **kwargs)
2825
self.id_letters = iter(u'ABCDEFGHIJK')
2926

3027
def _new_id(self):
3128
return next(self.id_letters)
32-
29+
3330
def start_kernel(self, kernel_id=None, path=None, kernel_name='python', **kwargs):
3431
kernel_id = kernel_id or self._new_id()
3532
k = self._kernels[kernel_id] = DummyKernel(kernel_name=kernel_name)
@@ -43,7 +40,7 @@ def shutdown_kernel(self, kernel_id, now=False):
4340

4441

4542
class TestSessionManager(TestCase):
46-
43+
4744
def setUp(self):
4845
self.sm = SessionManager(
4946
kernel_manager=DummyMKM(),
@@ -62,14 +59,14 @@ def co_add():
6259
sessions.append(session)
6360
raise gen.Return(sessions)
6461
return self.loop.run_sync(co_add)
65-
62+
6663
def create_session(self, **kwargs):
6764
return self.create_sessions(kwargs)[0]
6865

6966
def test_get_session(self):
7067
sm = self.sm
7168
session_id = self.create_session(path='/path/to/test.ipynb', kernel_name='bar')['id']
72-
model = sm.get_session(session_id=session_id)
69+
model = self.loop.run_sync(lambda: sm.get_session(session_id=session_id))
7370
expected = {'id':session_id,
7471
'path': u'/path/to/test.ipynb',
7572
'notebook': {'path': u'/path/to/test.ipynb', 'name': None},
@@ -89,17 +86,18 @@ def test_bad_get_session(self):
8986
sm = self.sm
9087
session_id = self.create_session(path='/path/to/test.ipynb',
9188
kernel_name='foo')['id']
92-
self.assertRaises(TypeError, sm.get_session, bad_id=session_id) # Bad keyword
89+
with self.assertRaises(TypeError):
90+
self.loop.run_sync(lambda: sm.get_session(bad_id=session_id)) # Bad keyword
9391

9492
def test_get_session_dead_kernel(self):
9593
sm = self.sm
9694
session = self.create_session(path='/path/to/1/test1.ipynb', kernel_name='python')
9795
# kill the kernel
9896
sm.kernel_manager.shutdown_kernel(session['kernel']['id'])
9997
with self.assertRaises(KeyError):
100-
sm.get_session(session_id=session['id'])
98+
self.loop.run_sync(lambda: sm.get_session(session_id=session['id']))
10199
# no sessions left
102-
listed = sm.list_sessions()
100+
listed = self.loop.run_sync(lambda: sm.list_sessions())
103101
self.assertEqual(listed, [])
104102

105103
def test_list_sessions(self):
@@ -109,8 +107,8 @@ def test_list_sessions(self):
109107
dict(path='/path/to/2/test2.py', type='file', kernel_name='python'),
110108
dict(path='/path/to/3', name='foo', type='console', kernel_name='python'),
111109
)
112-
113-
sessions = sm.list_sessions()
110+
111+
sessions = self.loop.run_sync(lambda: sm.list_sessions())
114112
expected = [
115113
{
116114
'id':sessions[0]['id'],
@@ -161,7 +159,7 @@ def test_list_sessions_dead_kernel(self):
161159
)
162160
# kill one of the kernels
163161
sm.kernel_manager.shutdown_kernel(sessions[0]['kernel']['id'])
164-
listed = sm.list_sessions()
162+
listed = self.loop.run_sync(lambda: sm.list_sessions())
165163
expected = [
166164
{
167165
'id': sessions[1]['id'],
@@ -184,8 +182,8 @@ def test_update_session(self):
184182
sm = self.sm
185183
session_id = self.create_session(path='/path/to/test.ipynb',
186184
kernel_name='julia')['id']
187-
sm.update_session(session_id, path='/path/to/new_name.ipynb')
188-
model = sm.get_session(session_id=session_id)
185+
self.loop.run_sync(lambda: sm.update_session(session_id, path='/path/to/new_name.ipynb'))
186+
model = self.loop.run_sync(lambda: sm.get_session(session_id=session_id))
189187
expected = {'id':session_id,
190188
'path': u'/path/to/new_name.ipynb',
191189
'type': 'notebook',
@@ -200,13 +198,14 @@ def test_update_session(self):
200198
}
201199
}
202200
self.assertEqual(model, expected)
203-
201+
204202
def test_bad_update_session(self):
205203
# try to update a session with a bad keyword ~ raise error
206204
sm = self.sm
207205
session_id = self.create_session(path='/path/to/test.ipynb',
208206
kernel_name='ir')['id']
209-
self.assertRaises(TypeError, sm.update_session, session_id=session_id, bad_kw='test.ipynb') # Bad keyword
207+
with self.assertRaises(TypeError):
208+
self.loop.run_sync(lambda: sm.update_session(session_id=session_id, bad_kw='test.ipynb')) # Bad keyword
210209

211210
def test_delete_session(self):
212211
sm = self.sm
@@ -215,8 +214,8 @@ def test_delete_session(self):
215214
dict(path='/path/to/2/test2.ipynb', kernel_name='python'),
216215
dict(path='/path/to/3', name='foo', type='console', kernel_name='python'),
217216
)
218-
sm.delete_session(sessions[1]['id'])
219-
new_sessions = sm.list_sessions()
217+
self.loop.run_sync(lambda: sm.delete_session(sessions[1]['id']))
218+
new_sessions = self.loop.run_sync(lambda: sm.list_sessions())
220219
expected = [{
221220
'id': sessions[0]['id'],
222221
'path': u'/path/to/1/test1.ipynb',

jupyter_server/utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,6 @@ def _check_pid_posix(pid):
385385

386386
def maybe_future(obj):
387387
"""Like tornado's deprecated gen.maybe_future
388-
389388
but more compatible with asyncio for recent versions
390389
of tornado
391390
"""

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
'nbval', 'nose-exclude', 'selenium', 'pytest', 'pytest-cov'],
9696
'test:sys_platform == "win32"': ['nose-exclude'],
9797
},
98-
python_requires='>=3.5',
98+
python_requires = '>=3.5',
9999
entry_points = {
100100
'console_scripts': [
101101
'jupyter-server = jupyter_server.serverapp:main',

0 commit comments

Comments
 (0)