##// END OF EJS Templates
TEST: Add checks for subdirectory name splitting....
Scott Sanderson -
Show More
@@ -1,400 +1,404 b''
1 1 # coding: utf-8
2 2 """Tests for the notebook manager."""
3 3 from __future__ import print_function
4 4
5 5 import os
6 6
7 7 from tornado.web import HTTPError
8 8 from unittest import TestCase
9 9 from tempfile import NamedTemporaryFile
10 10
11 11 from IPython.nbformat import v4 as nbformat
12 12
13 13 from IPython.utils.tempdir import TemporaryDirectory
14 14 from IPython.utils.traitlets import TraitError
15 15 from IPython.html.utils import url_path_join
16 16 from IPython.testing import decorators as dec
17 17
18 18 from ..filemanager import FileContentsManager
19 19
20 20
21 21 class TestFileContentsManager(TestCase):
22 22
23 23 def test_root_dir(self):
24 24 with TemporaryDirectory() as td:
25 25 fm = FileContentsManager(root_dir=td)
26 26 self.assertEqual(fm.root_dir, td)
27 27
28 28 def test_missing_root_dir(self):
29 29 with TemporaryDirectory() as td:
30 30 root = os.path.join(td, 'notebook', 'dir', 'is', 'missing')
31 31 self.assertRaises(TraitError, FileContentsManager, root_dir=root)
32 32
33 33 def test_invalid_root_dir(self):
34 34 with NamedTemporaryFile() as tf:
35 35 self.assertRaises(TraitError, FileContentsManager, root_dir=tf.name)
36 36
37 37 def test_get_os_path(self):
38 38 # full filesystem path should be returned with correct operating system
39 39 # separators.
40 40 with TemporaryDirectory() as td:
41 41 root = td
42 42 fm = FileContentsManager(root_dir=root)
43 43 path = fm._get_os_path('/path/to/notebook/test.ipynb')
44 44 rel_path_list = '/path/to/notebook/test.ipynb'.split('/')
45 45 fs_path = os.path.join(fm.root_dir, *rel_path_list)
46 46 self.assertEqual(path, fs_path)
47 47
48 48 fm = FileContentsManager(root_dir=root)
49 49 path = fm._get_os_path('test.ipynb')
50 50 fs_path = os.path.join(fm.root_dir, 'test.ipynb')
51 51 self.assertEqual(path, fs_path)
52 52
53 53 fm = FileContentsManager(root_dir=root)
54 54 path = fm._get_os_path('////test.ipynb')
55 55 fs_path = os.path.join(fm.root_dir, 'test.ipynb')
56 56 self.assertEqual(path, fs_path)
57 57
58 58 def test_checkpoint_subdir(self):
59 59 subd = u'sub βˆ‚ir'
60 60 cp_name = 'test-cp.ipynb'
61 61 with TemporaryDirectory() as td:
62 62 root = td
63 63 os.mkdir(os.path.join(td, subd))
64 64 fm = FileContentsManager(root_dir=root)
65 65 cp_dir = fm.get_checkpoint_path('cp', 'test.ipynb')
66 66 cp_subdir = fm.get_checkpoint_path('cp', '/%s/test.ipynb' % subd)
67 67 self.assertNotEqual(cp_dir, cp_subdir)
68 68 self.assertEqual(cp_dir, os.path.join(root, fm.checkpoint_dir, cp_name))
69 69 self.assertEqual(cp_subdir, os.path.join(root, subd, fm.checkpoint_dir, cp_name))
70 70
71 71
72 72 class TestContentsManager(TestCase):
73 73
74 74 def setUp(self):
75 75 self._temp_dir = TemporaryDirectory()
76 76 self.td = self._temp_dir.name
77 77 self.contents_manager = FileContentsManager(
78 78 root_dir=self.td,
79 79 )
80 80
81 81 def tearDown(self):
82 82 self._temp_dir.cleanup()
83 83
84 84 def make_dir(self, api_path):
85 85 """make subdirectory, rel_path is the relative path
86 86 to that directory from the location where the server started"""
87 87 os_path = self.contents_manager._get_os_path(api_path)
88 88 try:
89 89 os.makedirs(os_path)
90 90 except OSError:
91 91 print("Directory already exists: %r" % os_path)
92 92
93 93 def symlink(self, src, dst):
94 94 """Make a symlink to src from dst
95 95
96 96 src and dst are api_paths
97 97 """
98 98 src_os_path = self.contents_manager._get_os_path(src)
99 99 dst_os_path = self.contents_manager._get_os_path(dst)
100 100 print(src_os_path, dst_os_path, os.path.isfile(src_os_path))
101 101 os.symlink(src_os_path, dst_os_path)
102 102
103 103
104 104 def add_code_cell(self, nb):
105 105 output = nbformat.new_output("display_data", {'application/javascript': "alert('hi');"})
106 106 cell = nbformat.new_code_cell("print('hi')", outputs=[output])
107 107 nb.cells.append(cell)
108 108
109 109 def new_notebook(self):
110 110 cm = self.contents_manager
111 111 model = cm.new_untitled(type='notebook')
112 112 name = model['name']
113 113 path = model['path']
114 114
115 115 full_model = cm.get(path)
116 116 nb = full_model['content']
117 117 self.add_code_cell(nb)
118 118
119 119 cm.save(full_model, path)
120 120 return nb, name, path
121 121
122 122 def test_new_untitled(self):
123 123 cm = self.contents_manager
124 124 # Test in root directory
125 125 model = cm.new_untitled(type='notebook')
126 126 assert isinstance(model, dict)
127 127 self.assertIn('name', model)
128 128 self.assertIn('path', model)
129 129 self.assertIn('type', model)
130 130 self.assertEqual(model['type'], 'notebook')
131 131 self.assertEqual(model['name'], 'Untitled.ipynb')
132 132 self.assertEqual(model['path'], 'Untitled.ipynb')
133 133
134 134 # Test in sub-directory
135 135 model = cm.new_untitled(type='directory')
136 136 assert isinstance(model, dict)
137 137 self.assertIn('name', model)
138 138 self.assertIn('path', model)
139 139 self.assertIn('type', model)
140 140 self.assertEqual(model['type'], 'directory')
141 141 self.assertEqual(model['name'], 'Untitled Folder')
142 142 self.assertEqual(model['path'], 'Untitled Folder')
143 143 sub_dir = model['path']
144 144
145 145 model = cm.new_untitled(path=sub_dir)
146 146 assert isinstance(model, dict)
147 147 self.assertIn('name', model)
148 148 self.assertIn('path', model)
149 149 self.assertIn('type', model)
150 150 self.assertEqual(model['type'], 'file')
151 151 self.assertEqual(model['name'], 'untitled')
152 152 self.assertEqual(model['path'], '%s/untitled' % sub_dir)
153 153
154 154 def test_get(self):
155 155 cm = self.contents_manager
156 156 # Create a notebook
157 157 model = cm.new_untitled(type='notebook')
158 158 name = model['name']
159 159 path = model['path']
160 160
161 161 # Check that we 'get' on the notebook we just created
162 162 model2 = cm.get(path)
163 163 assert isinstance(model2, dict)
164 164 self.assertIn('name', model2)
165 165 self.assertIn('path', model2)
166 166 self.assertEqual(model['name'], name)
167 167 self.assertEqual(model['path'], path)
168 168
169 169 nb_as_file = cm.get(path, content=True, type='file')
170 170 self.assertEqual(nb_as_file['path'], path)
171 171 self.assertEqual(nb_as_file['type'], 'file')
172 172 self.assertEqual(nb_as_file['format'], 'text')
173 173 self.assertNotIsInstance(nb_as_file['content'], dict)
174 174
175 175 nb_as_bin_file = cm.get(path, content=True, type='file', format='base64')
176 176 self.assertEqual(nb_as_bin_file['format'], 'base64')
177 177
178 178 # Test in sub-directory
179 179 sub_dir = '/foo/'
180 180 self.make_dir('foo')
181 181 model = cm.new_untitled(path=sub_dir, ext='.ipynb')
182 182 model2 = cm.get(sub_dir + name)
183 183 assert isinstance(model2, dict)
184 184 self.assertIn('name', model2)
185 185 self.assertIn('path', model2)
186 186 self.assertIn('content', model2)
187 187 self.assertEqual(model2['name'], 'Untitled.ipynb')
188 188 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
189 189
190 190 # Test getting directory model
191 191
192 192 # Create a sub-sub directory to test getting directory contents with a
193 193 # subdir.
194 sub_sub_dir_path = 'foo/bar'
195 self.make_dir(sub_sub_dir_path)
194 self.make_dir('foo/bar')
196 195
197 196 dirmodel = cm.get('foo')
198 197 self.assertEqual(dirmodel['type'], 'directory')
199 198 self.assertIsInstance(dirmodel['content'], list)
200 199 self.assertEqual(len(dirmodel['content']), 2)
200 self.assertEqual(dirmodel['path'], 'foo')
201 self.assertEqual(dirmodel['name'], 'foo')
201 202
202 203 # Directory contents should match the contents of each individual entry
203 204 # when requested with content=False.
204 205 model2_no_content = cm.get(sub_dir + name, content=False)
205 sub_sub_dir_no_content = cm.get(sub_sub_dir_path, content=False)
206 sub_sub_dir_no_content = cm.get('foo/bar', content=False)
207 self.assertEqual(sub_sub_dir_no_content['path'], 'foo/bar')
208 self.assertEqual(sub_sub_dir_no_content['name'], 'bar')
209
206 210 for entry in dirmodel['content']:
207 211 # Order isn't guaranteed by the spec, so this is a hacky way of
208 212 # verifying that all entries are matched.
209 213 if entry['path'] == sub_sub_dir_no_content['path']:
210 214 self.assertEqual(entry, sub_sub_dir_no_content)
211 215 elif entry['path'] == model2_no_content['path']:
212 216 self.assertEqual(entry, model2_no_content)
213 217 else:
214 218 self.fail("Unexpected directory entry: %s" % entry())
215 219
216 220 with self.assertRaises(HTTPError):
217 221 cm.get('foo', type='file')
218 222
219 223
220 224 @dec.skip_win32
221 225 def test_bad_symlink(self):
222 226 cm = self.contents_manager
223 227 path = 'test bad symlink'
224 228 self.make_dir(path)
225 229
226 230 file_model = cm.new_untitled(path=path, ext='.txt')
227 231
228 232 # create a broken symlink
229 233 self.symlink("target", '%s/%s' % (path, 'bad symlink'))
230 234 model = cm.get(path)
231 235 self.assertEqual(model['content'], [file_model])
232 236
233 237 @dec.skip_win32
234 238 def test_good_symlink(self):
235 239 cm = self.contents_manager
236 240 parent = 'test good symlink'
237 241 name = 'good symlink'
238 242 path = '{0}/{1}'.format(parent, name)
239 243 self.make_dir(parent)
240 244
241 245 file_model = cm.new(path=parent + '/zfoo.txt')
242 246
243 247 # create a good symlink
244 248 self.symlink(file_model['path'], path)
245 249 symlink_model = cm.get(path, content=False)
246 250 dir_model = cm.get(parent)
247 251 self.assertEqual(
248 252 sorted(dir_model['content'], key=lambda x: x['name']),
249 253 [symlink_model, file_model],
250 254 )
251 255
252 256 def test_update(self):
253 257 cm = self.contents_manager
254 258 # Create a notebook
255 259 model = cm.new_untitled(type='notebook')
256 260 name = model['name']
257 261 path = model['path']
258 262
259 263 # Change the name in the model for rename
260 264 model['path'] = 'test.ipynb'
261 265 model = cm.update(model, path)
262 266 assert isinstance(model, dict)
263 267 self.assertIn('name', model)
264 268 self.assertIn('path', model)
265 269 self.assertEqual(model['name'], 'test.ipynb')
266 270
267 271 # Make sure the old name is gone
268 272 self.assertRaises(HTTPError, cm.get, path)
269 273
270 274 # Test in sub-directory
271 275 # Create a directory and notebook in that directory
272 276 sub_dir = '/foo/'
273 277 self.make_dir('foo')
274 278 model = cm.new_untitled(path=sub_dir, type='notebook')
275 279 path = model['path']
276 280
277 281 # Change the name in the model for rename
278 282 d = path.rsplit('/', 1)[0]
279 283 new_path = model['path'] = d + '/test_in_sub.ipynb'
280 284 model = cm.update(model, path)
281 285 assert isinstance(model, dict)
282 286 self.assertIn('name', model)
283 287 self.assertIn('path', model)
284 288 self.assertEqual(model['name'], 'test_in_sub.ipynb')
285 289 self.assertEqual(model['path'], new_path)
286 290
287 291 # Make sure the old name is gone
288 292 self.assertRaises(HTTPError, cm.get, path)
289 293
290 294 def test_save(self):
291 295 cm = self.contents_manager
292 296 # Create a notebook
293 297 model = cm.new_untitled(type='notebook')
294 298 name = model['name']
295 299 path = model['path']
296 300
297 301 # Get the model with 'content'
298 302 full_model = cm.get(path)
299 303
300 304 # Save the notebook
301 305 model = cm.save(full_model, path)
302 306 assert isinstance(model, dict)
303 307 self.assertIn('name', model)
304 308 self.assertIn('path', model)
305 309 self.assertEqual(model['name'], name)
306 310 self.assertEqual(model['path'], path)
307 311
308 312 # Test in sub-directory
309 313 # Create a directory and notebook in that directory
310 314 sub_dir = '/foo/'
311 315 self.make_dir('foo')
312 316 model = cm.new_untitled(path=sub_dir, type='notebook')
313 317 name = model['name']
314 318 path = model['path']
315 319 model = cm.get(path)
316 320
317 321 # Change the name in the model for rename
318 322 model = cm.save(model, path)
319 323 assert isinstance(model, dict)
320 324 self.assertIn('name', model)
321 325 self.assertIn('path', model)
322 326 self.assertEqual(model['name'], 'Untitled.ipynb')
323 327 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
324 328
325 329 def test_delete(self):
326 330 cm = self.contents_manager
327 331 # Create a notebook
328 332 nb, name, path = self.new_notebook()
329 333
330 334 # Delete the notebook
331 335 cm.delete(path)
332 336
333 337 # Check that deleting a non-existent path raises an error.
334 338 self.assertRaises(HTTPError, cm.delete, path)
335 339
336 340 # Check that a 'get' on the deleted notebook raises and error
337 341 self.assertRaises(HTTPError, cm.get, path)
338 342
339 343 def test_copy(self):
340 344 cm = self.contents_manager
341 345 parent = u'Γ₯ b'
342 346 name = u'nb √.ipynb'
343 347 path = u'{0}/{1}'.format(parent, name)
344 348 self.make_dir(parent)
345 349
346 350 orig = cm.new(path=path)
347 351 # copy with unspecified name
348 352 copy = cm.copy(path)
349 353 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
350 354
351 355 # copy with specified name
352 356 copy2 = cm.copy(path, u'Γ₯ b/copy 2.ipynb')
353 357 self.assertEqual(copy2['name'], u'copy 2.ipynb')
354 358 self.assertEqual(copy2['path'], u'Γ₯ b/copy 2.ipynb')
355 359 # copy with specified path
356 360 copy2 = cm.copy(path, u'/')
357 361 self.assertEqual(copy2['name'], name)
358 362 self.assertEqual(copy2['path'], name)
359 363
360 364 def test_trust_notebook(self):
361 365 cm = self.contents_manager
362 366 nb, name, path = self.new_notebook()
363 367
364 368 untrusted = cm.get(path)['content']
365 369 assert not cm.notary.check_cells(untrusted)
366 370
367 371 # print(untrusted)
368 372 cm.trust_notebook(path)
369 373 trusted = cm.get(path)['content']
370 374 # print(trusted)
371 375 assert cm.notary.check_cells(trusted)
372 376
373 377 def test_mark_trusted_cells(self):
374 378 cm = self.contents_manager
375 379 nb, name, path = self.new_notebook()
376 380
377 381 cm.mark_trusted_cells(nb, path)
378 382 for cell in nb.cells:
379 383 if cell.cell_type == 'code':
380 384 assert not cell.metadata.trusted
381 385
382 386 cm.trust_notebook(path)
383 387 nb = cm.get(path)['content']
384 388 for cell in nb.cells:
385 389 if cell.cell_type == 'code':
386 390 assert cell.metadata.trusted
387 391
388 392 def test_check_and_sign(self):
389 393 cm = self.contents_manager
390 394 nb, name, path = self.new_notebook()
391 395
392 396 cm.mark_trusted_cells(nb, path)
393 397 cm.check_and_sign(nb, path)
394 398 assert not cm.notary.check_signature(nb)
395 399
396 400 cm.trust_notebook(path)
397 401 nb = cm.get(path)['content']
398 402 cm.mark_trusted_cells(nb, path)
399 403 cm.check_and_sign(nb, path)
400 404 assert cm.notary.check_signature(nb)
General Comments 0
You need to be logged in to leave comments. Login now