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