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