##// END OF EJS Templates
TEST: Add test for handling of last_modified....
Scott Sanderson -
Show More
@@ -1,497 +1,521 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for the notebook manager."""
2 """Tests for the notebook manager."""
3 from __future__ import print_function
3 from __future__ import print_function
4
4
5 import os
5 import os
6 import sys
6 import sys
7 import time
7 import time
8 from contextlib import contextmanager
8 from contextlib import contextmanager
9
9
10 from nose import SkipTest
10 from nose import SkipTest
11 from tornado.web import HTTPError
11 from tornado.web import HTTPError
12 from unittest import TestCase
12 from unittest import TestCase
13 from tempfile import NamedTemporaryFile
13 from tempfile import NamedTemporaryFile
14
14
15 from IPython.nbformat import v4 as nbformat
15 from IPython.nbformat import v4 as nbformat
16
16
17 from IPython.utils.tempdir import TemporaryDirectory
17 from IPython.utils.tempdir import TemporaryDirectory
18 from IPython.utils.traitlets import TraitError
18 from IPython.utils.traitlets import TraitError
19 from IPython.testing import decorators as dec
19 from IPython.testing import decorators as dec
20
20
21 from ..filemanager import FileContentsManager
21 from ..filemanager import FileContentsManager
22
22
23
23
24 def _make_dir(contents_manager, api_path):
24 def _make_dir(contents_manager, api_path):
25 """
25 """
26 Make a directory.
26 Make a directory.
27 """
27 """
28 os_path = contents_manager._get_os_path(api_path)
28 os_path = contents_manager._get_os_path(api_path)
29 try:
29 try:
30 os.makedirs(os_path)
30 os.makedirs(os_path)
31 except OSError:
31 except OSError:
32 print("Directory already exists: %r" % os_path)
32 print("Directory already exists: %r" % os_path)
33
33
34
34
35 class TestFileContentsManager(TestCase):
35 class TestFileContentsManager(TestCase):
36
36
37 @contextmanager
37 @contextmanager
38 def assertRaisesHTTPError(self, status, msg=None):
38 def assertRaisesHTTPError(self, status, msg=None):
39 msg = msg or "Should have raised HTTPError(%i)" % status
39 msg = msg or "Should have raised HTTPError(%i)" % status
40 try:
40 try:
41 yield
41 yield
42 except HTTPError as e:
42 except HTTPError as e:
43 self.assertEqual(e.status_code, status)
43 self.assertEqual(e.status_code, status)
44 else:
44 else:
45 self.fail(msg)
45 self.fail(msg)
46
46
47 def symlink(self, contents_manager, src, dst):
47 def symlink(self, contents_manager, src, dst):
48 """Make a symlink to src from dst
48 """Make a symlink to src from dst
49
49
50 src and dst are api_paths
50 src and dst are api_paths
51 """
51 """
52 src_os_path = contents_manager._get_os_path(src)
52 src_os_path = contents_manager._get_os_path(src)
53 dst_os_path = contents_manager._get_os_path(dst)
53 dst_os_path = contents_manager._get_os_path(dst)
54 print(src_os_path, dst_os_path, os.path.isfile(src_os_path))
54 print(src_os_path, dst_os_path, os.path.isfile(src_os_path))
55 os.symlink(src_os_path, dst_os_path)
55 os.symlink(src_os_path, dst_os_path)
56
56
57 def test_root_dir(self):
57 def test_root_dir(self):
58 with TemporaryDirectory() as td:
58 with TemporaryDirectory() as td:
59 fm = FileContentsManager(root_dir=td)
59 fm = FileContentsManager(root_dir=td)
60 self.assertEqual(fm.root_dir, td)
60 self.assertEqual(fm.root_dir, td)
61
61
62 def test_missing_root_dir(self):
62 def test_missing_root_dir(self):
63 with TemporaryDirectory() as td:
63 with TemporaryDirectory() as td:
64 root = os.path.join(td, 'notebook', 'dir', 'is', 'missing')
64 root = os.path.join(td, 'notebook', 'dir', 'is', 'missing')
65 self.assertRaises(TraitError, FileContentsManager, root_dir=root)
65 self.assertRaises(TraitError, FileContentsManager, root_dir=root)
66
66
67 def test_invalid_root_dir(self):
67 def test_invalid_root_dir(self):
68 with NamedTemporaryFile() as tf:
68 with NamedTemporaryFile() as tf:
69 self.assertRaises(TraitError, FileContentsManager, root_dir=tf.name)
69 self.assertRaises(TraitError, FileContentsManager, root_dir=tf.name)
70
70
71 def test_get_os_path(self):
71 def test_get_os_path(self):
72 # full filesystem path should be returned with correct operating system
72 # full filesystem path should be returned with correct operating system
73 # separators.
73 # separators.
74 with TemporaryDirectory() as td:
74 with TemporaryDirectory() as td:
75 root = td
75 root = td
76 fm = FileContentsManager(root_dir=root)
76 fm = FileContentsManager(root_dir=root)
77 path = fm._get_os_path('/path/to/notebook/test.ipynb')
77 path = fm._get_os_path('/path/to/notebook/test.ipynb')
78 rel_path_list = '/path/to/notebook/test.ipynb'.split('/')
78 rel_path_list = '/path/to/notebook/test.ipynb'.split('/')
79 fs_path = os.path.join(fm.root_dir, *rel_path_list)
79 fs_path = os.path.join(fm.root_dir, *rel_path_list)
80 self.assertEqual(path, fs_path)
80 self.assertEqual(path, fs_path)
81
81
82 fm = FileContentsManager(root_dir=root)
82 fm = FileContentsManager(root_dir=root)
83 path = fm._get_os_path('test.ipynb')
83 path = fm._get_os_path('test.ipynb')
84 fs_path = os.path.join(fm.root_dir, 'test.ipynb')
84 fs_path = os.path.join(fm.root_dir, 'test.ipynb')
85 self.assertEqual(path, fs_path)
85 self.assertEqual(path, fs_path)
86
86
87 fm = FileContentsManager(root_dir=root)
87 fm = FileContentsManager(root_dir=root)
88 path = fm._get_os_path('////test.ipynb')
88 path = fm._get_os_path('////test.ipynb')
89 fs_path = os.path.join(fm.root_dir, 'test.ipynb')
89 fs_path = os.path.join(fm.root_dir, 'test.ipynb')
90 self.assertEqual(path, fs_path)
90 self.assertEqual(path, fs_path)
91
91
92 def test_checkpoint_subdir(self):
92 def test_checkpoint_subdir(self):
93 subd = u'sub βˆ‚ir'
93 subd = u'sub βˆ‚ir'
94 cp_name = 'test-cp.ipynb'
94 cp_name = 'test-cp.ipynb'
95 with TemporaryDirectory() as td:
95 with TemporaryDirectory() as td:
96 root = td
96 root = td
97 os.mkdir(os.path.join(td, subd))
97 os.mkdir(os.path.join(td, subd))
98 fm = FileContentsManager(root_dir=root)
98 fm = FileContentsManager(root_dir=root)
99 cpm = fm.checkpoints
99 cpm = fm.checkpoints
100 cp_dir = cpm.checkpoint_path(
100 cp_dir = cpm.checkpoint_path(
101 'cp', 'test.ipynb'
101 'cp', 'test.ipynb'
102 )
102 )
103 cp_subdir = cpm.checkpoint_path(
103 cp_subdir = cpm.checkpoint_path(
104 'cp', '/%s/test.ipynb' % subd
104 'cp', '/%s/test.ipynb' % subd
105 )
105 )
106 self.assertNotEqual(cp_dir, cp_subdir)
106 self.assertNotEqual(cp_dir, cp_subdir)
107 self.assertEqual(cp_dir, os.path.join(root, cpm.checkpoint_dir, cp_name))
107 self.assertEqual(cp_dir, os.path.join(root, cpm.checkpoint_dir, cp_name))
108 self.assertEqual(cp_subdir, os.path.join(root, subd, cpm.checkpoint_dir, cp_name))
108 self.assertEqual(cp_subdir, os.path.join(root, subd, cpm.checkpoint_dir, cp_name))
109
109
110 @dec.skip_win32
110 @dec.skip_win32
111 def test_bad_symlink(self):
111 def test_bad_symlink(self):
112 with TemporaryDirectory() as td:
112 with TemporaryDirectory() as td:
113 cm = FileContentsManager(root_dir=td)
113 cm = FileContentsManager(root_dir=td)
114 path = 'test bad symlink'
114 path = 'test bad symlink'
115 _make_dir(cm, path)
115 _make_dir(cm, path)
116
116
117 file_model = cm.new_untitled(path=path, ext='.txt')
117 file_model = cm.new_untitled(path=path, ext='.txt')
118
118
119 # create a broken symlink
119 # create a broken symlink
120 self.symlink(cm, "target", '%s/%s' % (path, 'bad symlink'))
120 self.symlink(cm, "target", '%s/%s' % (path, 'bad symlink'))
121 model = cm.get(path)
121 model = cm.get(path)
122 self.assertEqual(model['content'], [file_model])
122 self.assertEqual(model['content'], [file_model])
123
123
124 @dec.skip_win32
124 @dec.skip_win32
125 def test_good_symlink(self):
125 def test_good_symlink(self):
126 with TemporaryDirectory() as td:
126 with TemporaryDirectory() as td:
127 cm = FileContentsManager(root_dir=td)
127 cm = FileContentsManager(root_dir=td)
128 parent = 'test good symlink'
128 parent = 'test good symlink'
129 name = 'good symlink'
129 name = 'good symlink'
130 path = '{0}/{1}'.format(parent, name)
130 path = '{0}/{1}'.format(parent, name)
131 _make_dir(cm, parent)
131 _make_dir(cm, parent)
132
132
133 file_model = cm.new(path=parent + '/zfoo.txt')
133 file_model = cm.new(path=parent + '/zfoo.txt')
134
134
135 # create a good symlink
135 # create a good symlink
136 self.symlink(cm, file_model['path'], path)
136 self.symlink(cm, file_model['path'], path)
137 symlink_model = cm.get(path, content=False)
137 symlink_model = cm.get(path, content=False)
138 dir_model = cm.get(parent)
138 dir_model = cm.get(parent)
139 self.assertEqual(
139 self.assertEqual(
140 sorted(dir_model['content'], key=lambda x: x['name']),
140 sorted(dir_model['content'], key=lambda x: x['name']),
141 [symlink_model, file_model],
141 [symlink_model, file_model],
142 )
142 )
143
143
144 def test_403(self):
144 def test_403(self):
145 if hasattr(os, 'getuid'):
145 if hasattr(os, 'getuid'):
146 if os.getuid() == 0:
146 if os.getuid() == 0:
147 raise SkipTest("Can't test permissions as root")
147 raise SkipTest("Can't test permissions as root")
148 if sys.platform.startswith('win'):
148 if sys.platform.startswith('win'):
149 raise SkipTest("Can't test permissions on Windows")
149 raise SkipTest("Can't test permissions on Windows")
150
150
151 with TemporaryDirectory() as td:
151 with TemporaryDirectory() as td:
152 cm = FileContentsManager(root_dir=td)
152 cm = FileContentsManager(root_dir=td)
153 model = cm.new_untitled(type='file')
153 model = cm.new_untitled(type='file')
154 os_path = cm._get_os_path(model['path'])
154 os_path = cm._get_os_path(model['path'])
155
155
156 os.chmod(os_path, 0o400)
156 os.chmod(os_path, 0o400)
157 try:
157 try:
158 with cm.open(os_path, 'w') as f:
158 with cm.open(os_path, 'w') as f:
159 f.write(u"don't care")
159 f.write(u"don't care")
160 except HTTPError as e:
160 except HTTPError as e:
161 self.assertEqual(e.status_code, 403)
161 self.assertEqual(e.status_code, 403)
162 else:
162 else:
163 self.fail("Should have raised HTTPError(403)")
163 self.fail("Should have raised HTTPError(403)")
164
164
165 def test_escape_root(self):
165 def test_escape_root(self):
166 with TemporaryDirectory() as td:
166 with TemporaryDirectory() as td:
167 cm = FileContentsManager(root_dir=td)
167 cm = FileContentsManager(root_dir=td)
168 # make foo, bar next to root
168 # make foo, bar next to root
169 with open(os.path.join(cm.root_dir, '..', 'foo'), 'w') as f:
169 with open(os.path.join(cm.root_dir, '..', 'foo'), 'w') as f:
170 f.write('foo')
170 f.write('foo')
171 with open(os.path.join(cm.root_dir, '..', 'bar'), 'w') as f:
171 with open(os.path.join(cm.root_dir, '..', 'bar'), 'w') as f:
172 f.write('bar')
172 f.write('bar')
173
173
174 with self.assertRaisesHTTPError(404):
174 with self.assertRaisesHTTPError(404):
175 cm.get('..')
175 cm.get('..')
176 with self.assertRaisesHTTPError(404):
176 with self.assertRaisesHTTPError(404):
177 cm.get('foo/../../../bar')
177 cm.get('foo/../../../bar')
178 with self.assertRaisesHTTPError(404):
178 with self.assertRaisesHTTPError(404):
179 cm.delete('../foo')
179 cm.delete('../foo')
180 with self.assertRaisesHTTPError(404):
180 with self.assertRaisesHTTPError(404):
181 cm.rename('../foo', '../bar')
181 cm.rename('../foo', '../bar')
182 with self.assertRaisesHTTPError(404):
182 with self.assertRaisesHTTPError(404):
183 cm.save(model={
183 cm.save(model={
184 'type': 'file',
184 'type': 'file',
185 'content': u'',
185 'content': u'',
186 'format': 'text',
186 'format': 'text',
187 }, path='../foo')
187 }, path='../foo')
188
188
189
189
190 class TestContentsManager(TestCase):
190 class TestContentsManager(TestCase):
191
191
192 def setUp(self):
192 def setUp(self):
193 self._temp_dir = TemporaryDirectory()
193 self._temp_dir = TemporaryDirectory()
194 self.td = self._temp_dir.name
194 self.td = self._temp_dir.name
195 self.contents_manager = FileContentsManager(
195 self.contents_manager = FileContentsManager(
196 root_dir=self.td,
196 root_dir=self.td,
197 )
197 )
198
198
199 def tearDown(self):
199 def tearDown(self):
200 self._temp_dir.cleanup()
200 self._temp_dir.cleanup()
201
201
202 def make_dir(self, api_path):
202 def make_dir(self, api_path):
203 """make a subdirectory at api_path
203 """make a subdirectory at api_path
204
204
205 override in subclasses if contents are not on the filesystem.
205 override in subclasses if contents are not on the filesystem.
206 """
206 """
207 _make_dir(self.contents_manager, api_path)
207 _make_dir(self.contents_manager, api_path)
208
208
209 def add_code_cell(self, nb):
209 def add_code_cell(self, nb):
210 output = nbformat.new_output("display_data", {'application/javascript': "alert('hi');"})
210 output = nbformat.new_output("display_data", {'application/javascript': "alert('hi');"})
211 cell = nbformat.new_code_cell("print('hi')", outputs=[output])
211 cell = nbformat.new_code_cell("print('hi')", outputs=[output])
212 nb.cells.append(cell)
212 nb.cells.append(cell)
213
213
214 def new_notebook(self):
214 def new_notebook(self):
215 cm = self.contents_manager
215 cm = self.contents_manager
216 model = cm.new_untitled(type='notebook')
216 model = cm.new_untitled(type='notebook')
217 name = model['name']
217 name = model['name']
218 path = model['path']
218 path = model['path']
219
219
220 full_model = cm.get(path)
220 full_model = cm.get(path)
221 nb = full_model['content']
221 nb = full_model['content']
222 nb['metadata']['counter'] = int(1e6 * time.time())
222 nb['metadata']['counter'] = int(1e6 * time.time())
223 self.add_code_cell(nb)
223 self.add_code_cell(nb)
224
224
225 cm.save(full_model, path)
225 cm.save(full_model, path)
226 return nb, name, path
226 return nb, name, path
227
227
228 def test_new_untitled(self):
228 def test_new_untitled(self):
229 cm = self.contents_manager
229 cm = self.contents_manager
230 # Test in root directory
230 # Test in root directory
231 model = cm.new_untitled(type='notebook')
231 model = cm.new_untitled(type='notebook')
232 assert isinstance(model, dict)
232 assert isinstance(model, dict)
233 self.assertIn('name', model)
233 self.assertIn('name', model)
234 self.assertIn('path', model)
234 self.assertIn('path', model)
235 self.assertIn('type', model)
235 self.assertIn('type', model)
236 self.assertEqual(model['type'], 'notebook')
236 self.assertEqual(model['type'], 'notebook')
237 self.assertEqual(model['name'], 'Untitled.ipynb')
237 self.assertEqual(model['name'], 'Untitled.ipynb')
238 self.assertEqual(model['path'], 'Untitled.ipynb')
238 self.assertEqual(model['path'], 'Untitled.ipynb')
239
239
240 # Test in sub-directory
240 # Test in sub-directory
241 model = cm.new_untitled(type='directory')
241 model = cm.new_untitled(type='directory')
242 assert isinstance(model, dict)
242 assert isinstance(model, dict)
243 self.assertIn('name', model)
243 self.assertIn('name', model)
244 self.assertIn('path', model)
244 self.assertIn('path', model)
245 self.assertIn('type', model)
245 self.assertIn('type', model)
246 self.assertEqual(model['type'], 'directory')
246 self.assertEqual(model['type'], 'directory')
247 self.assertEqual(model['name'], 'Untitled Folder')
247 self.assertEqual(model['name'], 'Untitled Folder')
248 self.assertEqual(model['path'], 'Untitled Folder')
248 self.assertEqual(model['path'], 'Untitled Folder')
249 sub_dir = model['path']
249 sub_dir = model['path']
250
250
251 model = cm.new_untitled(path=sub_dir)
251 model = cm.new_untitled(path=sub_dir)
252 assert isinstance(model, dict)
252 assert isinstance(model, dict)
253 self.assertIn('name', model)
253 self.assertIn('name', model)
254 self.assertIn('path', model)
254 self.assertIn('path', model)
255 self.assertIn('type', model)
255 self.assertIn('type', model)
256 self.assertEqual(model['type'], 'file')
256 self.assertEqual(model['type'], 'file')
257 self.assertEqual(model['name'], 'untitled')
257 self.assertEqual(model['name'], 'untitled')
258 self.assertEqual(model['path'], '%s/untitled' % sub_dir)
258 self.assertEqual(model['path'], '%s/untitled' % sub_dir)
259
259
260 def test_modified_date(self):
261
262 cm = self.contents_manager
263
264 # Create a new notebook.
265 nb, name, path = self.new_notebook()
266 model = cm.get(path)
267
268 # Add a cell and save.
269 self.add_code_cell(model['content'])
270 cm.save(model, path)
271
272 # Reload notebook and verify that last_modified incremented.
273 saved = cm.get(path)
274 self.assertGreater(saved['last_modified'], model['last_modified'])
275
276 # Move the notebook and verify that last_modified stayed the same.
277 # (The frontend fires a warning if last_modified increases on the
278 # renamed file.)
279 new_path = 'renamed.ipynb'
280 cm.rename(path, new_path)
281 renamed = cm.get(new_path)
282 self.assertEqual(renamed['last_modified'], saved['last_modified'])
283
260 def test_get(self):
284 def test_get(self):
261 cm = self.contents_manager
285 cm = self.contents_manager
262 # Create a notebook
286 # Create a notebook
263 model = cm.new_untitled(type='notebook')
287 model = cm.new_untitled(type='notebook')
264 name = model['name']
288 name = model['name']
265 path = model['path']
289 path = model['path']
266
290
267 # Check that we 'get' on the notebook we just created
291 # Check that we 'get' on the notebook we just created
268 model2 = cm.get(path)
292 model2 = cm.get(path)
269 assert isinstance(model2, dict)
293 assert isinstance(model2, dict)
270 self.assertIn('name', model2)
294 self.assertIn('name', model2)
271 self.assertIn('path', model2)
295 self.assertIn('path', model2)
272 self.assertEqual(model['name'], name)
296 self.assertEqual(model['name'], name)
273 self.assertEqual(model['path'], path)
297 self.assertEqual(model['path'], path)
274
298
275 nb_as_file = cm.get(path, content=True, type='file')
299 nb_as_file = cm.get(path, content=True, type='file')
276 self.assertEqual(nb_as_file['path'], path)
300 self.assertEqual(nb_as_file['path'], path)
277 self.assertEqual(nb_as_file['type'], 'file')
301 self.assertEqual(nb_as_file['type'], 'file')
278 self.assertEqual(nb_as_file['format'], 'text')
302 self.assertEqual(nb_as_file['format'], 'text')
279 self.assertNotIsInstance(nb_as_file['content'], dict)
303 self.assertNotIsInstance(nb_as_file['content'], dict)
280
304
281 nb_as_bin_file = cm.get(path, content=True, type='file', format='base64')
305 nb_as_bin_file = cm.get(path, content=True, type='file', format='base64')
282 self.assertEqual(nb_as_bin_file['format'], 'base64')
306 self.assertEqual(nb_as_bin_file['format'], 'base64')
283
307
284 # Test in sub-directory
308 # Test in sub-directory
285 sub_dir = '/foo/'
309 sub_dir = '/foo/'
286 self.make_dir('foo')
310 self.make_dir('foo')
287 model = cm.new_untitled(path=sub_dir, ext='.ipynb')
311 model = cm.new_untitled(path=sub_dir, ext='.ipynb')
288 model2 = cm.get(sub_dir + name)
312 model2 = cm.get(sub_dir + name)
289 assert isinstance(model2, dict)
313 assert isinstance(model2, dict)
290 self.assertIn('name', model2)
314 self.assertIn('name', model2)
291 self.assertIn('path', model2)
315 self.assertIn('path', model2)
292 self.assertIn('content', model2)
316 self.assertIn('content', model2)
293 self.assertEqual(model2['name'], 'Untitled.ipynb')
317 self.assertEqual(model2['name'], 'Untitled.ipynb')
294 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
318 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
295
319
296 # Test with a regular file.
320 # Test with a regular file.
297 file_model_path = cm.new_untitled(path=sub_dir, ext='.txt')['path']
321 file_model_path = cm.new_untitled(path=sub_dir, ext='.txt')['path']
298 file_model = cm.get(file_model_path)
322 file_model = cm.get(file_model_path)
299 self.assertDictContainsSubset(
323 self.assertDictContainsSubset(
300 {
324 {
301 'content': u'',
325 'content': u'',
302 'format': u'text',
326 'format': u'text',
303 'mimetype': u'text/plain',
327 'mimetype': u'text/plain',
304 'name': u'untitled.txt',
328 'name': u'untitled.txt',
305 'path': u'foo/untitled.txt',
329 'path': u'foo/untitled.txt',
306 'type': u'file',
330 'type': u'file',
307 'writable': True,
331 'writable': True,
308 },
332 },
309 file_model,
333 file_model,
310 )
334 )
311 self.assertIn('created', file_model)
335 self.assertIn('created', file_model)
312 self.assertIn('last_modified', file_model)
336 self.assertIn('last_modified', file_model)
313
337
314 # Test getting directory model
338 # Test getting directory model
315
339
316 # Create a sub-sub directory to test getting directory contents with a
340 # Create a sub-sub directory to test getting directory contents with a
317 # subdir.
341 # subdir.
318 self.make_dir('foo/bar')
342 self.make_dir('foo/bar')
319 dirmodel = cm.get('foo')
343 dirmodel = cm.get('foo')
320 self.assertEqual(dirmodel['type'], 'directory')
344 self.assertEqual(dirmodel['type'], 'directory')
321 self.assertIsInstance(dirmodel['content'], list)
345 self.assertIsInstance(dirmodel['content'], list)
322 self.assertEqual(len(dirmodel['content']), 3)
346 self.assertEqual(len(dirmodel['content']), 3)
323 self.assertEqual(dirmodel['path'], 'foo')
347 self.assertEqual(dirmodel['path'], 'foo')
324 self.assertEqual(dirmodel['name'], 'foo')
348 self.assertEqual(dirmodel['name'], 'foo')
325
349
326 # Directory contents should match the contents of each individual entry
350 # Directory contents should match the contents of each individual entry
327 # when requested with content=False.
351 # when requested with content=False.
328 model2_no_content = cm.get(sub_dir + name, content=False)
352 model2_no_content = cm.get(sub_dir + name, content=False)
329 file_model_no_content = cm.get(u'foo/untitled.txt', content=False)
353 file_model_no_content = cm.get(u'foo/untitled.txt', content=False)
330 sub_sub_dir_no_content = cm.get('foo/bar', content=False)
354 sub_sub_dir_no_content = cm.get('foo/bar', content=False)
331 self.assertEqual(sub_sub_dir_no_content['path'], 'foo/bar')
355 self.assertEqual(sub_sub_dir_no_content['path'], 'foo/bar')
332 self.assertEqual(sub_sub_dir_no_content['name'], 'bar')
356 self.assertEqual(sub_sub_dir_no_content['name'], 'bar')
333
357
334 for entry in dirmodel['content']:
358 for entry in dirmodel['content']:
335 # Order isn't guaranteed by the spec, so this is a hacky way of
359 # Order isn't guaranteed by the spec, so this is a hacky way of
336 # verifying that all entries are matched.
360 # verifying that all entries are matched.
337 if entry['path'] == sub_sub_dir_no_content['path']:
361 if entry['path'] == sub_sub_dir_no_content['path']:
338 self.assertEqual(entry, sub_sub_dir_no_content)
362 self.assertEqual(entry, sub_sub_dir_no_content)
339 elif entry['path'] == model2_no_content['path']:
363 elif entry['path'] == model2_no_content['path']:
340 self.assertEqual(entry, model2_no_content)
364 self.assertEqual(entry, model2_no_content)
341 elif entry['path'] == file_model_no_content['path']:
365 elif entry['path'] == file_model_no_content['path']:
342 self.assertEqual(entry, file_model_no_content)
366 self.assertEqual(entry, file_model_no_content)
343 else:
367 else:
344 self.fail("Unexpected directory entry: %s" % entry())
368 self.fail("Unexpected directory entry: %s" % entry())
345
369
346 with self.assertRaises(HTTPError):
370 with self.assertRaises(HTTPError):
347 cm.get('foo', type='file')
371 cm.get('foo', type='file')
348
372
349 def test_update(self):
373 def test_update(self):
350 cm = self.contents_manager
374 cm = self.contents_manager
351 # Create a notebook
375 # Create a notebook
352 model = cm.new_untitled(type='notebook')
376 model = cm.new_untitled(type='notebook')
353 name = model['name']
377 name = model['name']
354 path = model['path']
378 path = model['path']
355
379
356 # Change the name in the model for rename
380 # Change the name in the model for rename
357 model['path'] = 'test.ipynb'
381 model['path'] = 'test.ipynb'
358 model = cm.update(model, path)
382 model = cm.update(model, path)
359 assert isinstance(model, dict)
383 assert isinstance(model, dict)
360 self.assertIn('name', model)
384 self.assertIn('name', model)
361 self.assertIn('path', model)
385 self.assertIn('path', model)
362 self.assertEqual(model['name'], 'test.ipynb')
386 self.assertEqual(model['name'], 'test.ipynb')
363
387
364 # Make sure the old name is gone
388 # Make sure the old name is gone
365 self.assertRaises(HTTPError, cm.get, path)
389 self.assertRaises(HTTPError, cm.get, path)
366
390
367 # Test in sub-directory
391 # Test in sub-directory
368 # Create a directory and notebook in that directory
392 # Create a directory and notebook in that directory
369 sub_dir = '/foo/'
393 sub_dir = '/foo/'
370 self.make_dir('foo')
394 self.make_dir('foo')
371 model = cm.new_untitled(path=sub_dir, type='notebook')
395 model = cm.new_untitled(path=sub_dir, type='notebook')
372 path = model['path']
396 path = model['path']
373
397
374 # Change the name in the model for rename
398 # Change the name in the model for rename
375 d = path.rsplit('/', 1)[0]
399 d = path.rsplit('/', 1)[0]
376 new_path = model['path'] = d + '/test_in_sub.ipynb'
400 new_path = model['path'] = d + '/test_in_sub.ipynb'
377 model = cm.update(model, path)
401 model = cm.update(model, path)
378 assert isinstance(model, dict)
402 assert isinstance(model, dict)
379 self.assertIn('name', model)
403 self.assertIn('name', model)
380 self.assertIn('path', model)
404 self.assertIn('path', model)
381 self.assertEqual(model['name'], 'test_in_sub.ipynb')
405 self.assertEqual(model['name'], 'test_in_sub.ipynb')
382 self.assertEqual(model['path'], new_path)
406 self.assertEqual(model['path'], new_path)
383
407
384 # Make sure the old name is gone
408 # Make sure the old name is gone
385 self.assertRaises(HTTPError, cm.get, path)
409 self.assertRaises(HTTPError, cm.get, path)
386
410
387 def test_save(self):
411 def test_save(self):
388 cm = self.contents_manager
412 cm = self.contents_manager
389 # Create a notebook
413 # Create a notebook
390 model = cm.new_untitled(type='notebook')
414 model = cm.new_untitled(type='notebook')
391 name = model['name']
415 name = model['name']
392 path = model['path']
416 path = model['path']
393
417
394 # Get the model with 'content'
418 # Get the model with 'content'
395 full_model = cm.get(path)
419 full_model = cm.get(path)
396
420
397 # Save the notebook
421 # Save the notebook
398 model = cm.save(full_model, path)
422 model = cm.save(full_model, path)
399 assert isinstance(model, dict)
423 assert isinstance(model, dict)
400 self.assertIn('name', model)
424 self.assertIn('name', model)
401 self.assertIn('path', model)
425 self.assertIn('path', model)
402 self.assertEqual(model['name'], name)
426 self.assertEqual(model['name'], name)
403 self.assertEqual(model['path'], path)
427 self.assertEqual(model['path'], path)
404
428
405 # Test in sub-directory
429 # Test in sub-directory
406 # Create a directory and notebook in that directory
430 # Create a directory and notebook in that directory
407 sub_dir = '/foo/'
431 sub_dir = '/foo/'
408 self.make_dir('foo')
432 self.make_dir('foo')
409 model = cm.new_untitled(path=sub_dir, type='notebook')
433 model = cm.new_untitled(path=sub_dir, type='notebook')
410 name = model['name']
434 name = model['name']
411 path = model['path']
435 path = model['path']
412 model = cm.get(path)
436 model = cm.get(path)
413
437
414 # Change the name in the model for rename
438 # Change the name in the model for rename
415 model = cm.save(model, path)
439 model = cm.save(model, path)
416 assert isinstance(model, dict)
440 assert isinstance(model, dict)
417 self.assertIn('name', model)
441 self.assertIn('name', model)
418 self.assertIn('path', model)
442 self.assertIn('path', model)
419 self.assertEqual(model['name'], 'Untitled.ipynb')
443 self.assertEqual(model['name'], 'Untitled.ipynb')
420 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
444 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
421
445
422 def test_delete(self):
446 def test_delete(self):
423 cm = self.contents_manager
447 cm = self.contents_manager
424 # Create a notebook
448 # Create a notebook
425 nb, name, path = self.new_notebook()
449 nb, name, path = self.new_notebook()
426
450
427 # Delete the notebook
451 # Delete the notebook
428 cm.delete(path)
452 cm.delete(path)
429
453
430 # Check that deleting a non-existent path raises an error.
454 # Check that deleting a non-existent path raises an error.
431 self.assertRaises(HTTPError, cm.delete, path)
455 self.assertRaises(HTTPError, cm.delete, path)
432
456
433 # Check that a 'get' on the deleted notebook raises and error
457 # Check that a 'get' on the deleted notebook raises and error
434 self.assertRaises(HTTPError, cm.get, path)
458 self.assertRaises(HTTPError, cm.get, path)
435
459
436 def test_copy(self):
460 def test_copy(self):
437 cm = self.contents_manager
461 cm = self.contents_manager
438 parent = u'Γ₯ b'
462 parent = u'Γ₯ b'
439 name = u'nb √.ipynb'
463 name = u'nb √.ipynb'
440 path = u'{0}/{1}'.format(parent, name)
464 path = u'{0}/{1}'.format(parent, name)
441 self.make_dir(parent)
465 self.make_dir(parent)
442
466
443 orig = cm.new(path=path)
467 orig = cm.new(path=path)
444 # copy with unspecified name
468 # copy with unspecified name
445 copy = cm.copy(path)
469 copy = cm.copy(path)
446 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
470 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
447
471
448 # copy with specified name
472 # copy with specified name
449 copy2 = cm.copy(path, u'Γ₯ b/copy 2.ipynb')
473 copy2 = cm.copy(path, u'Γ₯ b/copy 2.ipynb')
450 self.assertEqual(copy2['name'], u'copy 2.ipynb')
474 self.assertEqual(copy2['name'], u'copy 2.ipynb')
451 self.assertEqual(copy2['path'], u'Γ₯ b/copy 2.ipynb')
475 self.assertEqual(copy2['path'], u'Γ₯ b/copy 2.ipynb')
452 # copy with specified path
476 # copy with specified path
453 copy2 = cm.copy(path, u'/')
477 copy2 = cm.copy(path, u'/')
454 self.assertEqual(copy2['name'], name)
478 self.assertEqual(copy2['name'], name)
455 self.assertEqual(copy2['path'], name)
479 self.assertEqual(copy2['path'], name)
456
480
457 def test_trust_notebook(self):
481 def test_trust_notebook(self):
458 cm = self.contents_manager
482 cm = self.contents_manager
459 nb, name, path = self.new_notebook()
483 nb, name, path = self.new_notebook()
460
484
461 untrusted = cm.get(path)['content']
485 untrusted = cm.get(path)['content']
462 assert not cm.notary.check_cells(untrusted)
486 assert not cm.notary.check_cells(untrusted)
463
487
464 # print(untrusted)
488 # print(untrusted)
465 cm.trust_notebook(path)
489 cm.trust_notebook(path)
466 trusted = cm.get(path)['content']
490 trusted = cm.get(path)['content']
467 # print(trusted)
491 # print(trusted)
468 assert cm.notary.check_cells(trusted)
492 assert cm.notary.check_cells(trusted)
469
493
470 def test_mark_trusted_cells(self):
494 def test_mark_trusted_cells(self):
471 cm = self.contents_manager
495 cm = self.contents_manager
472 nb, name, path = self.new_notebook()
496 nb, name, path = self.new_notebook()
473
497
474 cm.mark_trusted_cells(nb, path)
498 cm.mark_trusted_cells(nb, path)
475 for cell in nb.cells:
499 for cell in nb.cells:
476 if cell.cell_type == 'code':
500 if cell.cell_type == 'code':
477 assert not cell.metadata.trusted
501 assert not cell.metadata.trusted
478
502
479 cm.trust_notebook(path)
503 cm.trust_notebook(path)
480 nb = cm.get(path)['content']
504 nb = cm.get(path)['content']
481 for cell in nb.cells:
505 for cell in nb.cells:
482 if cell.cell_type == 'code':
506 if cell.cell_type == 'code':
483 assert cell.metadata.trusted
507 assert cell.metadata.trusted
484
508
485 def test_check_and_sign(self):
509 def test_check_and_sign(self):
486 cm = self.contents_manager
510 cm = self.contents_manager
487 nb, name, path = self.new_notebook()
511 nb, name, path = self.new_notebook()
488
512
489 cm.mark_trusted_cells(nb, path)
513 cm.mark_trusted_cells(nb, path)
490 cm.check_and_sign(nb, path)
514 cm.check_and_sign(nb, path)
491 assert not cm.notary.check_signature(nb)
515 assert not cm.notary.check_signature(nb)
492
516
493 cm.trust_notebook(path)
517 cm.trust_notebook(path)
494 nb = cm.get(path)['content']
518 nb = cm.get(path)['content']
495 cm.mark_trusted_cells(nb, path)
519 cm.mark_trusted_cells(nb, path)
496 cm.check_and_sign(nb, path)
520 cm.check_and_sign(nb, path)
497 assert cm.notary.check_signature(nb)
521 assert cm.notary.check_signature(nb)
General Comments 0
You need to be logged in to leave comments. Login now