##// END OF EJS Templates
TEST: Expect a 404 on delete of non-existent file.
Scott Sanderson -
Show More
@@ -1,375 +1,378 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 dirmodel = cm.get('foo')
192 192 self.assertEqual(dirmodel['type'], 'directory')
193 193
194 194 with self.assertRaises(HTTPError):
195 195 cm.get('foo', type='file')
196 196
197 197
198 198 @dec.skip_win32
199 199 def test_bad_symlink(self):
200 200 cm = self.contents_manager
201 201 path = 'test bad symlink'
202 202 self.make_dir(path)
203 203
204 204 file_model = cm.new_untitled(path=path, ext='.txt')
205 205
206 206 # create a broken symlink
207 207 self.symlink("target", '%s/%s' % (path, 'bad symlink'))
208 208 model = cm.get(path)
209 209 self.assertEqual(model['content'], [file_model])
210 210
211 211 @dec.skip_win32
212 212 def test_good_symlink(self):
213 213 cm = self.contents_manager
214 214 parent = 'test good symlink'
215 215 name = 'good symlink'
216 216 path = '{0}/{1}'.format(parent, name)
217 217 self.make_dir(parent)
218 218
219 219 file_model = cm.new(path=parent + '/zfoo.txt')
220 220
221 221 # create a good symlink
222 222 self.symlink(file_model['path'], path)
223 223 symlink_model = cm.get(path, content=False)
224 224 dir_model = cm.get(parent)
225 225 self.assertEqual(
226 226 sorted(dir_model['content'], key=lambda x: x['name']),
227 227 [symlink_model, file_model],
228 228 )
229 229
230 230 def test_update(self):
231 231 cm = self.contents_manager
232 232 # Create a notebook
233 233 model = cm.new_untitled(type='notebook')
234 234 name = model['name']
235 235 path = model['path']
236 236
237 237 # Change the name in the model for rename
238 238 model['path'] = 'test.ipynb'
239 239 model = cm.update(model, path)
240 240 assert isinstance(model, dict)
241 241 self.assertIn('name', model)
242 242 self.assertIn('path', model)
243 243 self.assertEqual(model['name'], 'test.ipynb')
244 244
245 245 # Make sure the old name is gone
246 246 self.assertRaises(HTTPError, cm.get, path)
247 247
248 248 # Test in sub-directory
249 249 # Create a directory and notebook in that directory
250 250 sub_dir = '/foo/'
251 251 self.make_dir('foo')
252 252 model = cm.new_untitled(path=sub_dir, type='notebook')
253 253 path = model['path']
254 254
255 255 # Change the name in the model for rename
256 256 d = path.rsplit('/', 1)[0]
257 257 new_path = model['path'] = d + '/test_in_sub.ipynb'
258 258 model = cm.update(model, path)
259 259 assert isinstance(model, dict)
260 260 self.assertIn('name', model)
261 261 self.assertIn('path', model)
262 262 self.assertEqual(model['name'], 'test_in_sub.ipynb')
263 263 self.assertEqual(model['path'], new_path)
264 264
265 265 # Make sure the old name is gone
266 266 self.assertRaises(HTTPError, cm.get, path)
267 267
268 268 def test_save(self):
269 269 cm = self.contents_manager
270 270 # Create a notebook
271 271 model = cm.new_untitled(type='notebook')
272 272 name = model['name']
273 273 path = model['path']
274 274
275 275 # Get the model with 'content'
276 276 full_model = cm.get(path)
277 277
278 278 # Save the notebook
279 279 model = cm.save(full_model, path)
280 280 assert isinstance(model, dict)
281 281 self.assertIn('name', model)
282 282 self.assertIn('path', model)
283 283 self.assertEqual(model['name'], name)
284 284 self.assertEqual(model['path'], path)
285 285
286 286 # Test in sub-directory
287 287 # Create a directory and notebook in that directory
288 288 sub_dir = '/foo/'
289 289 self.make_dir('foo')
290 290 model = cm.new_untitled(path=sub_dir, type='notebook')
291 291 name = model['name']
292 292 path = model['path']
293 293 model = cm.get(path)
294 294
295 295 # Change the name in the model for rename
296 296 model = cm.save(model, path)
297 297 assert isinstance(model, dict)
298 298 self.assertIn('name', model)
299 299 self.assertIn('path', model)
300 300 self.assertEqual(model['name'], 'Untitled.ipynb')
301 301 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
302 302
303 303 def test_delete(self):
304 304 cm = self.contents_manager
305 305 # Create a notebook
306 306 nb, name, path = self.new_notebook()
307 307
308 308 # Delete the notebook
309 309 cm.delete(path)
310 310
311 # Check that deleting a non-existent path raises an error.
312 self.assertRaises(HTTPError, cm.delete, path)
313
311 314 # Check that a 'get' on the deleted notebook raises and error
312 315 self.assertRaises(HTTPError, cm.get, path)
313 316
314 317 def test_copy(self):
315 318 cm = self.contents_manager
316 319 parent = u'Γ₯ b'
317 320 name = u'nb √.ipynb'
318 321 path = u'{0}/{1}'.format(parent, name)
319 322 self.make_dir(parent)
320 orig = cm.new(path=path)
321 323
324 orig = cm.new(path=path)
322 325 # copy with unspecified name
323 326 copy = cm.copy(path)
324 327 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
325 328
326 329 # copy with specified name
327 330 copy2 = cm.copy(path, u'Γ₯ b/copy 2.ipynb')
328 331 self.assertEqual(copy2['name'], u'copy 2.ipynb')
329 332 self.assertEqual(copy2['path'], u'Γ₯ b/copy 2.ipynb')
330 333 # copy with specified path
331 334 copy2 = cm.copy(path, u'/')
332 335 self.assertEqual(copy2['name'], name)
333 336 self.assertEqual(copy2['path'], name)
334 337
335 338 def test_trust_notebook(self):
336 339 cm = self.contents_manager
337 340 nb, name, path = self.new_notebook()
338 341
339 342 untrusted = cm.get(path)['content']
340 343 assert not cm.notary.check_cells(untrusted)
341 344
342 345 # print(untrusted)
343 346 cm.trust_notebook(path)
344 347 trusted = cm.get(path)['content']
345 348 # print(trusted)
346 349 assert cm.notary.check_cells(trusted)
347 350
348 351 def test_mark_trusted_cells(self):
349 352 cm = self.contents_manager
350 353 nb, name, path = self.new_notebook()
351 354
352 355 cm.mark_trusted_cells(nb, path)
353 356 for cell in nb.cells:
354 357 if cell.cell_type == 'code':
355 358 assert not cell.metadata.trusted
356 359
357 360 cm.trust_notebook(path)
358 361 nb = cm.get(path)['content']
359 362 for cell in nb.cells:
360 363 if cell.cell_type == 'code':
361 364 assert cell.metadata.trusted
362 365
363 366 def test_check_and_sign(self):
364 367 cm = self.contents_manager
365 368 nb, name, path = self.new_notebook()
366 369
367 370 cm.mark_trusted_cells(nb, path)
368 371 cm.check_and_sign(nb, path)
369 372 assert not cm.notary.check_signature(nb)
370 373
371 374 cm.trust_notebook(path)
372 375 nb = cm.get(path)['content']
373 376 cm.mark_trusted_cells(nb, path)
374 377 cm.check_and_sign(nb, path)
375 378 assert cm.notary.check_signature(nb)
General Comments 0
You need to be logged in to leave comments. Login now