1
+ import time
1
2
import json
3
+ import shutil
2
4
import pytest
3
5
6
+ import tornado
4
7
5
- def get_session_model (
6
- path ,
7
- type = 'notebook' ,
8
- kernel_name = 'python' ,
9
- kernel_id = None
10
- ):
11
- return {
12
- 'path' : path ,
13
- 'type' : type ,
14
- 'kernel' : {
15
- 'name' : kernel_name ,
16
- 'id' : kernel_id
8
+ from nbformat .v4 import new_notebook
9
+ from nbformat import writes
10
+
11
+ from ...conftest import expected_http_error
12
+
13
+ j = lambda r : json .loads (r .body .decode ())
14
+
15
+
16
+ class SessionClient :
17
+
18
+ def __init__ (self , fetch_callable ):
19
+ self .fetch = fetch_callable
20
+
21
+ async def _req (self , * args , method , body = None ):
22
+ if body is not None :
23
+ body = json .dumps (body )
24
+
25
+ r = await self .fetch (
26
+ 'api' , 'sessions' , * args ,
27
+ method = method ,
28
+ body = body ,
29
+ allow_nonstandard_methods = True
30
+ )
31
+ return r
32
+
33
+ async def list (self ):
34
+ return await self ._req (method = 'GET' )
35
+
36
+ async def get (self , id ):
37
+ return await self ._req (id , method = 'GET' )
38
+
39
+ async def create (
40
+ self ,
41
+ path ,
42
+ type = 'notebook' ,
43
+ kernel_name = 'python' ,
44
+ kernel_id = None ):
45
+ body = {
46
+ 'path' : path ,
47
+ 'type' : type ,
48
+ 'kernel' : {
49
+ 'name' : kernel_name ,
50
+ 'id' : kernel_id
51
+ }
17
52
}
18
- }
53
+ return await self ._req (method = 'POST' , body = body )
54
+
55
+ def create_deprecated (self , path ):
56
+ body = {
57
+ 'notebook' : {
58
+ 'path' : path
59
+ },
60
+ 'kernel' : {
61
+ 'name' : 'python' ,
62
+ 'id' : 'foo'
63
+ }
64
+ }
65
+ return self ._req (method = 'POST' , body = body )
66
+
67
+ def modify_path (self , id , path ):
68
+ body = {'path' : path }
69
+ return self ._req (id , method = 'PATCH' , body = body )
70
+
71
+ def modify_path_deprecated (self , id , path ):
72
+ body = {'notebook' : {'path' : path }}
73
+ return self ._req (id , method = 'PATCH' , body = body )
19
74
75
+ def modify_type (self , id , type ):
76
+ body = {'type' : type }
77
+ return self ._req (id , method = 'PATCH' , body = body )
20
78
21
- async def test_create (fetch ):
79
+ def modify_kernel_name (self , id , kernel_name ):
80
+ body = {'kernel' : {'name' : kernel_name }}
81
+ return self ._req (id , method = 'PATCH' , body = body )
82
+
83
+ def modify_kernel_id (self , id , kernel_id ):
84
+ # Also send a dummy name to show that id takes precedence.
85
+ body = {'kernel' : {'id' : kernel_id , 'name' : 'foo' }}
86
+ return self ._req (id , method = 'PATCH' , body = body )
87
+
88
+ async def delete (self , id ):
89
+ return await self ._req (id , method = 'DELETE' )
90
+
91
+ async def cleanup (self ):
92
+ resp = await self .list ()
93
+ sessions = j (resp )
94
+ for session in sessions :
95
+ await self .delete (session ['id' ])
96
+ time .sleep (0.1 )
97
+
98
+
99
+
100
+ @pytest .fixture
101
+ def session_client (root_dir , fetch ):
102
+ subdir = root_dir .joinpath ('foo' )
103
+ subdir .mkdir ()
104
+
105
+ # Write a notebook to subdir.
106
+ nb = new_notebook ()
107
+ nb_str = writes (nb , version = 4 )
108
+ nbpath = subdir .joinpath ('nb1.ipynb' )
109
+ nbpath .write_text (nb_str , encoding = 'utf-8' )
110
+
111
+ # Yield a session client
112
+ client = SessionClient (fetch )
113
+ yield client
114
+
115
+ # Remove subdir
116
+ shutil .rmtree (str (subdir ), ignore_errors = True )
117
+
118
+
119
+ async def test_create (session_client ):
22
120
# Make sure no sessions exist.
23
- r = await fetch (
24
- 'api' , 'sessions' ,
25
- method = 'GET'
26
- )
27
- sessions = json .loads (r .body .decode ())
121
+ resp = await session_client .list ()
122
+ sessions = j (resp )
28
123
assert len (sessions ) == 0
29
124
30
125
# Create a session.
31
- model = get_session_model ('foo/nb1.ipynb' )
32
- r = await fetch (
33
- 'api' , 'sessions' ,
34
- method = 'POST' ,
35
- body = json .dumps (model )
36
- )
37
- assert r .code == 201
38
- new_session = json .loads (r .body .decode ())
126
+ resp = await session_client .create ('foo/nb1.ipynb' )
127
+ assert resp .code == 201
128
+ new_session = j (resp )
39
129
assert 'id' in new_session
40
130
assert new_session ['path' ] == 'foo/nb1.ipynb'
41
131
assert new_session ['type' ] == 'notebook'
42
- assert r .headers ['Location' ] == '/api/sessions/' + new_session ['id' ]
132
+ assert resp .headers ['Location' ] == '/api/sessions/' + new_session ['id' ]
43
133
44
134
# Check that the new session appears in list.
45
- r = await fetch (
46
- 'api' , 'sessions' ,
47
- method = 'GET'
48
- )
49
- sessions = json .loads (r .body .decode ())
135
+ resp = await session_client .list ()
136
+ sessions = j (resp )
50
137
assert sessions == [new_session ]
51
138
52
139
# Retrieve that session.
53
140
sid = new_session ['id' ]
54
- r = await fetch (
55
- 'api' , 'sessions' , sid ,
56
- method = 'GET'
57
- )
58
- got = json .loads (r .body .decode ())
141
+ resp = await session_client .get (sid )
142
+ got = j (resp )
59
143
assert got == new_session
60
144
145
+ # Need to find a better solution to this.
146
+ await session_client .cleanup ()
147
+
148
+
149
+ async def test_create_file_session (session_client ):
150
+ resp = await session_client .create ('foo/nb1.py' , type = 'file' )
151
+ assert resp .code == 201
152
+ newsession = j (resp )
153
+ assert newsession ['path' ] == 'foo/nb1.py'
154
+ assert newsession ['type' ] == 'file'
155
+ await session_client .cleanup ()
156
+
157
+
158
+ async def test_create_console_session (session_client ):
159
+ resp = await session_client .create ('foo/abc123' , type = 'console' )
160
+ assert resp .code == 201
161
+ newsession = j (resp )
162
+ assert newsession ['path' ] == 'foo/abc123'
163
+ assert newsession ['type' ] == 'console'
164
+ # Need to find a better solution to this.
165
+ await session_client .cleanup ()
166
+
167
+
168
+ async def test_create_deprecated (session_client ):
169
+ resp = await session_client .create_deprecated ('foo/nb1.ipynb' )
170
+ assert resp .code == 201
171
+ newsession = j (resp )
172
+ assert newsession ['path' ] == 'foo/nb1.ipynb'
173
+ assert newsession ['type' ] == 'notebook'
174
+ assert newsession ['notebook' ]['path' ] == 'foo/nb1.ipynb'
175
+ # Need to find a better solution to this.
176
+ await session_client .cleanup ()
177
+
178
+
179
+ async def test_create_with_kernel_id (session_client , fetch ):
180
+ # create a new kernel
181
+ resp = await fetch ('api/kernels' , method = 'POST' , allow_nonstandard_methods = True )
182
+ kernel = j (resp )
183
+
184
+ resp = await session_client .create ('foo/nb1.ipynb' , kernel_id = kernel ['id' ])
185
+ assert resp .code == 201
186
+ newsession = j (resp )
187
+ assert 'id' in newsession
188
+ assert newsession ['path' ] == 'foo/nb1.ipynb'
189
+ assert newsession ['kernel' ]['id' ] == kernel ['id' ]
190
+ assert resp .headers ['Location' ] == '/api/sessions/{0}' .format (newsession ['id' ])
191
+
192
+ resp = await session_client .list ()
193
+ sessions = j (resp )
194
+ assert sessions == [newsession ]
195
+
196
+ # Retrieve it
197
+ sid = newsession ['id' ]
198
+ resp = await session_client .get (sid )
199
+ got = j (resp )
200
+ assert got == newsession
201
+ # Need to find a better solution to this.
202
+ await session_client .cleanup ()
203
+
204
+ async def test_delete (session_client ):
205
+ resp = await session_client .create ('foo/nb1.ipynb' )
206
+ newsession = j (resp )
207
+ sid = newsession ['id' ]
208
+
209
+ resp = await session_client .delete (sid )
210
+ assert resp .code == 204
211
+
212
+ resp = await session_client .list ()
213
+ sessions = j (resp )
214
+ assert sessions == []
215
+
216
+ with pytest .raises (tornado .httpclient .HTTPClientError ) as e :
217
+ await session_client .get (sid )
218
+ assert expected_http_error (e , 404 )
219
+ # Need to find a better solution to this.
220
+ await session_client .cleanup ()
221
+
222
+ async def test_modify_path (session_client ):
223
+ resp = await session_client .create ('foo/nb1.ipynb' )
224
+ newsession = j (resp )
225
+ sid = newsession ['id' ]
226
+
227
+ resp = await session_client .modify_path (sid , 'nb2.ipynb' )
228
+ changed = j (resp )
229
+ assert changed ['id' ] == sid
230
+ assert changed ['path' ] == 'nb2.ipynb'
231
+ # Need to find a better solution to this.
232
+ await session_client .cleanup ()
233
+
234
+ async def test_modify_path_deprecated (session_client ):
235
+ resp = await session_client .create ('foo/nb1.ipynb' )
236
+ newsession = j (resp )
237
+ sid = newsession ['id' ]
238
+
239
+ resp = await session_client .modify_path_deprecated (sid , 'nb2.ipynb' )
240
+ changed = j (resp )
241
+ assert changed ['id' ] == sid
242
+ assert changed ['notebook' ]['path' ] == 'nb2.ipynb'
243
+ # Need to find a better solution to this.
244
+ await session_client .cleanup ()
245
+
246
+ async def test_modify_type (session_client ):
247
+ resp = await session_client .create ('foo/nb1.ipynb' )
248
+ newsession = j (resp )
249
+ sid = newsession ['id' ]
250
+
251
+ resp = await session_client .modify_type (sid , 'console' )
252
+ changed = j (resp )
253
+ assert changed ['id' ] == sid
254
+ assert changed ['type' ] == 'console'
255
+ # Need to find a better solution to this.
256
+ await session_client .cleanup ()
257
+
258
+ async def test_modify_kernel_name (session_client , fetch ):
259
+ resp = await session_client .create ('foo/nb1.ipynb' )
260
+ before = j (resp )
261
+ sid = before ['id' ]
262
+
263
+ resp = await session_client .modify_kernel_name (sid , before ['kernel' ]['name' ])
264
+ after = j (resp )
265
+ assert after ['id' ] == sid
266
+ assert after ['path' ] == before ['path' ]
267
+ assert after ['type' ] == before ['type' ]
268
+ assert after ['kernel' ]['id' ] != before ['kernel' ]['id' ]
269
+
270
+ # check kernel list, to be sure previous kernel was cleaned up
271
+ resp = await fetch ('api/kernels' , method = 'GET' )
272
+ kernel_list = j (resp )
273
+ after ['kernel' ].pop ('last_activity' )
274
+ [ k .pop ('last_activity' ) for k in kernel_list ]
275
+ assert kernel_list == [after ['kernel' ]]
276
+ # Need to find a better solution to this.
277
+ await session_client .cleanup ()
278
+
279
+
280
+ async def test_modify_kernel_id (session_client , fetch ):
281
+ resp = await session_client .create ('foo/nb1.ipynb' )
282
+ before = j (resp )
283
+ sid = before ['id' ]
284
+
285
+ # create a new kernel
286
+ resp = await fetch ('api/kernels' , method = 'POST' , allow_nonstandard_methods = True )
287
+ kernel = j (resp )
288
+
289
+ # Attach our session to the existing kernel
290
+ resp = await session_client .modify_kernel_id (sid , kernel ['id' ])
291
+ after = j (resp )
292
+ assert after ['id' ] == sid
293
+ assert after ['path' ] == before ['path' ]
294
+ assert after ['type' ] == before ['type' ]
295
+ assert after ['kernel' ]['id' ] != before ['kernel' ]['id' ]
296
+ assert after ['kernel' ]['id' ] == kernel ['id' ]
297
+
298
+ # check kernel list, to be sure previous kernel was cleaned up
299
+ resp = await fetch ('api/kernels' , method = 'GET' )
300
+ kernel_list = j (resp )
301
+
302
+ kernel .pop ('last_activity' )
303
+ [ k .pop ('last_activity' ) for k in kernel_list ]
304
+ assert kernel_list == [kernel ]
61
305
306
+ # Need to find a better solution to this.
307
+ await session_client .cleanup ()
0 commit comments