##// END OF EJS Templates
use >= instead of > when comparing dates...
Min RK -
Show More
@@ -1,524 +1,524 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):
260 def test_modified_date(self):
261
261
262 cm = self.contents_manager
262 cm = self.contents_manager
263
263
264 # Create a new notebook.
264 # Create a new notebook.
265 nb, name, path = self.new_notebook()
265 nb, name, path = self.new_notebook()
266 model = cm.get(path)
266 model = cm.get(path)
267
267
268 # Add a cell and save.
268 # Add a cell and save.
269 self.add_code_cell(model['content'])
269 self.add_code_cell(model['content'])
270 cm.save(model, path)
270 cm.save(model, path)
271
271
272 # Reload notebook and verify that last_modified incremented.
272 # Reload notebook and verify that last_modified incremented.
273 saved = cm.get(path)
273 saved = cm.get(path)
274 self.assertGreater(saved['last_modified'], model['last_modified'])
274 self.assertGreaterEqual(saved['last_modified'], model['last_modified'])
275
275
276 # Move the notebook and verify that last_modified stayed the same.
276 # Move the notebook and verify that last_modified stayed the same.
277 # (The frontend fires a warning if last_modified increases on the
277 # (The frontend fires a warning if last_modified increases on the
278 # renamed file.)
278 # renamed file.)
279 new_path = 'renamed.ipynb'
279 new_path = 'renamed.ipynb'
280 cm.rename(path, new_path)
280 cm.rename(path, new_path)
281 renamed = cm.get(new_path)
281 renamed = cm.get(new_path)
282 self.assertGreaterEqual(
282 self.assertGreaterEqual(
283 renamed['last_modified'],
283 renamed['last_modified'],
284 saved['last_modified'],
284 saved['last_modified'],
285 )
285 )
286
286
287 def test_get(self):
287 def test_get(self):
288 cm = self.contents_manager
288 cm = self.contents_manager
289 # Create a notebook
289 # Create a notebook
290 model = cm.new_untitled(type='notebook')
290 model = cm.new_untitled(type='notebook')
291 name = model['name']
291 name = model['name']
292 path = model['path']
292 path = model['path']
293
293
294 # Check that we 'get' on the notebook we just created
294 # Check that we 'get' on the notebook we just created
295 model2 = cm.get(path)
295 model2 = cm.get(path)
296 assert isinstance(model2, dict)
296 assert isinstance(model2, dict)
297 self.assertIn('name', model2)
297 self.assertIn('name', model2)
298 self.assertIn('path', model2)
298 self.assertIn('path', model2)
299 self.assertEqual(model['name'], name)
299 self.assertEqual(model['name'], name)
300 self.assertEqual(model['path'], path)
300 self.assertEqual(model['path'], path)
301
301
302 nb_as_file = cm.get(path, content=True, type='file')
302 nb_as_file = cm.get(path, content=True, type='file')
303 self.assertEqual(nb_as_file['path'], path)
303 self.assertEqual(nb_as_file['path'], path)
304 self.assertEqual(nb_as_file['type'], 'file')
304 self.assertEqual(nb_as_file['type'], 'file')
305 self.assertEqual(nb_as_file['format'], 'text')
305 self.assertEqual(nb_as_file['format'], 'text')
306 self.assertNotIsInstance(nb_as_file['content'], dict)
306 self.assertNotIsInstance(nb_as_file['content'], dict)
307
307
308 nb_as_bin_file = cm.get(path, content=True, type='file', format='base64')
308 nb_as_bin_file = cm.get(path, content=True, type='file', format='base64')
309 self.assertEqual(nb_as_bin_file['format'], 'base64')
309 self.assertEqual(nb_as_bin_file['format'], 'base64')
310
310
311 # Test in sub-directory
311 # Test in sub-directory
312 sub_dir = '/foo/'
312 sub_dir = '/foo/'
313 self.make_dir('foo')
313 self.make_dir('foo')
314 model = cm.new_untitled(path=sub_dir, ext='.ipynb')
314 model = cm.new_untitled(path=sub_dir, ext='.ipynb')
315 model2 = cm.get(sub_dir + name)
315 model2 = cm.get(sub_dir + name)
316 assert isinstance(model2, dict)
316 assert isinstance(model2, dict)
317 self.assertIn('name', model2)
317 self.assertIn('name', model2)
318 self.assertIn('path', model2)
318 self.assertIn('path', model2)
319 self.assertIn('content', model2)
319 self.assertIn('content', model2)
320 self.assertEqual(model2['name'], 'Untitled.ipynb')
320 self.assertEqual(model2['name'], 'Untitled.ipynb')
321 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
321 self.assertEqual(model2['path'], '{0}/{1}'.format(sub_dir.strip('/'), name))
322
322
323 # Test with a regular file.
323 # Test with a regular file.
324 file_model_path = cm.new_untitled(path=sub_dir, ext='.txt')['path']
324 file_model_path = cm.new_untitled(path=sub_dir, ext='.txt')['path']
325 file_model = cm.get(file_model_path)
325 file_model = cm.get(file_model_path)
326 self.assertDictContainsSubset(
326 self.assertDictContainsSubset(
327 {
327 {
328 'content': u'',
328 'content': u'',
329 'format': u'text',
329 'format': u'text',
330 'mimetype': u'text/plain',
330 'mimetype': u'text/plain',
331 'name': u'untitled.txt',
331 'name': u'untitled.txt',
332 'path': u'foo/untitled.txt',
332 'path': u'foo/untitled.txt',
333 'type': u'file',
333 'type': u'file',
334 'writable': True,
334 'writable': True,
335 },
335 },
336 file_model,
336 file_model,
337 )
337 )
338 self.assertIn('created', file_model)
338 self.assertIn('created', file_model)
339 self.assertIn('last_modified', file_model)
339 self.assertIn('last_modified', file_model)
340
340
341 # Test getting directory model
341 # Test getting directory model
342
342
343 # Create a sub-sub directory to test getting directory contents with a
343 # Create a sub-sub directory to test getting directory contents with a
344 # subdir.
344 # subdir.
345 self.make_dir('foo/bar')
345 self.make_dir('foo/bar')
346 dirmodel = cm.get('foo')
346 dirmodel = cm.get('foo')
347 self.assertEqual(dirmodel['type'], 'directory')
347 self.assertEqual(dirmodel['type'], 'directory')
348 self.assertIsInstance(dirmodel['content'], list)
348 self.assertIsInstance(dirmodel['content'], list)
349 self.assertEqual(len(dirmodel['content']), 3)
349 self.assertEqual(len(dirmodel['content']), 3)
350 self.assertEqual(dirmodel['path'], 'foo')
350 self.assertEqual(dirmodel['path'], 'foo')
351 self.assertEqual(dirmodel['name'], 'foo')
351 self.assertEqual(dirmodel['name'], 'foo')
352
352
353 # Directory contents should match the contents of each individual entry
353 # Directory contents should match the contents of each individual entry
354 # when requested with content=False.
354 # when requested with content=False.
355 model2_no_content = cm.get(sub_dir + name, content=False)
355 model2_no_content = cm.get(sub_dir + name, content=False)
356 file_model_no_content = cm.get(u'foo/untitled.txt', content=False)
356 file_model_no_content = cm.get(u'foo/untitled.txt', content=False)
357 sub_sub_dir_no_content = cm.get('foo/bar', content=False)
357 sub_sub_dir_no_content = cm.get('foo/bar', content=False)
358 self.assertEqual(sub_sub_dir_no_content['path'], 'foo/bar')
358 self.assertEqual(sub_sub_dir_no_content['path'], 'foo/bar')
359 self.assertEqual(sub_sub_dir_no_content['name'], 'bar')
359 self.assertEqual(sub_sub_dir_no_content['name'], 'bar')
360
360
361 for entry in dirmodel['content']:
361 for entry in dirmodel['content']:
362 # Order isn't guaranteed by the spec, so this is a hacky way of
362 # Order isn't guaranteed by the spec, so this is a hacky way of
363 # verifying that all entries are matched.
363 # verifying that all entries are matched.
364 if entry['path'] == sub_sub_dir_no_content['path']:
364 if entry['path'] == sub_sub_dir_no_content['path']:
365 self.assertEqual(entry, sub_sub_dir_no_content)
365 self.assertEqual(entry, sub_sub_dir_no_content)
366 elif entry['path'] == model2_no_content['path']:
366 elif entry['path'] == model2_no_content['path']:
367 self.assertEqual(entry, model2_no_content)
367 self.assertEqual(entry, model2_no_content)
368 elif entry['path'] == file_model_no_content['path']:
368 elif entry['path'] == file_model_no_content['path']:
369 self.assertEqual(entry, file_model_no_content)
369 self.assertEqual(entry, file_model_no_content)
370 else:
370 else:
371 self.fail("Unexpected directory entry: %s" % entry())
371 self.fail("Unexpected directory entry: %s" % entry())
372
372
373 with self.assertRaises(HTTPError):
373 with self.assertRaises(HTTPError):
374 cm.get('foo', type='file')
374 cm.get('foo', type='file')
375
375
376 def test_update(self):
376 def test_update(self):
377 cm = self.contents_manager
377 cm = self.contents_manager
378 # Create a notebook
378 # Create a notebook
379 model = cm.new_untitled(type='notebook')
379 model = cm.new_untitled(type='notebook')
380 name = model['name']
380 name = model['name']
381 path = model['path']
381 path = model['path']
382
382
383 # Change the name in the model for rename
383 # Change the name in the model for rename
384 model['path'] = 'test.ipynb'
384 model['path'] = 'test.ipynb'
385 model = cm.update(model, path)
385 model = cm.update(model, path)
386 assert isinstance(model, dict)
386 assert isinstance(model, dict)
387 self.assertIn('name', model)
387 self.assertIn('name', model)
388 self.assertIn('path', model)
388 self.assertIn('path', model)
389 self.assertEqual(model['name'], 'test.ipynb')
389 self.assertEqual(model['name'], 'test.ipynb')
390
390
391 # Make sure the old name is gone
391 # Make sure the old name is gone
392 self.assertRaises(HTTPError, cm.get, path)
392 self.assertRaises(HTTPError, cm.get, path)
393
393
394 # Test in sub-directory
394 # Test in sub-directory
395 # Create a directory and notebook in that directory
395 # Create a directory and notebook in that directory
396 sub_dir = '/foo/'
396 sub_dir = '/foo/'
397 self.make_dir('foo')
397 self.make_dir('foo')
398 model = cm.new_untitled(path=sub_dir, type='notebook')
398 model = cm.new_untitled(path=sub_dir, type='notebook')
399 path = model['path']
399 path = model['path']
400
400
401 # Change the name in the model for rename
401 # Change the name in the model for rename
402 d = path.rsplit('/', 1)[0]
402 d = path.rsplit('/', 1)[0]
403 new_path = model['path'] = d + '/test_in_sub.ipynb'
403 new_path = model['path'] = d + '/test_in_sub.ipynb'
404 model = cm.update(model, path)
404 model = cm.update(model, path)
405 assert isinstance(model, dict)
405 assert isinstance(model, dict)
406 self.assertIn('name', model)
406 self.assertIn('name', model)
407 self.assertIn('path', model)
407 self.assertIn('path', model)
408 self.assertEqual(model['name'], 'test_in_sub.ipynb')
408 self.assertEqual(model['name'], 'test_in_sub.ipynb')
409 self.assertEqual(model['path'], new_path)
409 self.assertEqual(model['path'], new_path)
410
410
411 # Make sure the old name is gone
411 # Make sure the old name is gone
412 self.assertRaises(HTTPError, cm.get, path)
412 self.assertRaises(HTTPError, cm.get, path)
413
413
414 def test_save(self):
414 def test_save(self):
415 cm = self.contents_manager
415 cm = self.contents_manager
416 # Create a notebook
416 # Create a notebook
417 model = cm.new_untitled(type='notebook')
417 model = cm.new_untitled(type='notebook')
418 name = model['name']
418 name = model['name']
419 path = model['path']
419 path = model['path']
420
420
421 # Get the model with 'content'
421 # Get the model with 'content'
422 full_model = cm.get(path)
422 full_model = cm.get(path)
423
423
424 # Save the notebook
424 # Save the notebook
425 model = cm.save(full_model, path)
425 model = cm.save(full_model, path)
426 assert isinstance(model, dict)
426 assert isinstance(model, dict)
427 self.assertIn('name', model)
427 self.assertIn('name', model)
428 self.assertIn('path', model)
428 self.assertIn('path', model)
429 self.assertEqual(model['name'], name)
429 self.assertEqual(model['name'], name)
430 self.assertEqual(model['path'], path)
430 self.assertEqual(model['path'], path)
431
431
432 # Test in sub-directory
432 # Test in sub-directory
433 # Create a directory and notebook in that directory
433 # Create a directory and notebook in that directory
434 sub_dir = '/foo/'
434 sub_dir = '/foo/'
435 self.make_dir('foo')
435 self.make_dir('foo')
436 model = cm.new_untitled(path=sub_dir, type='notebook')
436 model = cm.new_untitled(path=sub_dir, type='notebook')
437 name = model['name']
437 name = model['name']
438 path = model['path']
438 path = model['path']
439 model = cm.get(path)
439 model = cm.get(path)
440
440
441 # Change the name in the model for rename
441 # Change the name in the model for rename
442 model = cm.save(model, path)
442 model = cm.save(model, path)
443 assert isinstance(model, dict)
443 assert isinstance(model, dict)
444 self.assertIn('name', model)
444 self.assertIn('name', model)
445 self.assertIn('path', model)
445 self.assertIn('path', model)
446 self.assertEqual(model['name'], 'Untitled.ipynb')
446 self.assertEqual(model['name'], 'Untitled.ipynb')
447 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
447 self.assertEqual(model['path'], 'foo/Untitled.ipynb')
448
448
449 def test_delete(self):
449 def test_delete(self):
450 cm = self.contents_manager
450 cm = self.contents_manager
451 # Create a notebook
451 # Create a notebook
452 nb, name, path = self.new_notebook()
452 nb, name, path = self.new_notebook()
453
453
454 # Delete the notebook
454 # Delete the notebook
455 cm.delete(path)
455 cm.delete(path)
456
456
457 # Check that deleting a non-existent path raises an error.
457 # Check that deleting a non-existent path raises an error.
458 self.assertRaises(HTTPError, cm.delete, path)
458 self.assertRaises(HTTPError, cm.delete, path)
459
459
460 # Check that a 'get' on the deleted notebook raises and error
460 # Check that a 'get' on the deleted notebook raises and error
461 self.assertRaises(HTTPError, cm.get, path)
461 self.assertRaises(HTTPError, cm.get, path)
462
462
463 def test_copy(self):
463 def test_copy(self):
464 cm = self.contents_manager
464 cm = self.contents_manager
465 parent = u'Γ₯ b'
465 parent = u'Γ₯ b'
466 name = u'nb √.ipynb'
466 name = u'nb √.ipynb'
467 path = u'{0}/{1}'.format(parent, name)
467 path = u'{0}/{1}'.format(parent, name)
468 self.make_dir(parent)
468 self.make_dir(parent)
469
469
470 orig = cm.new(path=path)
470 orig = cm.new(path=path)
471 # copy with unspecified name
471 # copy with unspecified name
472 copy = cm.copy(path)
472 copy = cm.copy(path)
473 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
473 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy1.ipynb'))
474
474
475 # copy with specified name
475 # copy with specified name
476 copy2 = cm.copy(path, u'Γ₯ b/copy 2.ipynb')
476 copy2 = cm.copy(path, u'Γ₯ b/copy 2.ipynb')
477 self.assertEqual(copy2['name'], u'copy 2.ipynb')
477 self.assertEqual(copy2['name'], u'copy 2.ipynb')
478 self.assertEqual(copy2['path'], u'Γ₯ b/copy 2.ipynb')
478 self.assertEqual(copy2['path'], u'Γ₯ b/copy 2.ipynb')
479 # copy with specified path
479 # copy with specified path
480 copy2 = cm.copy(path, u'/')
480 copy2 = cm.copy(path, u'/')
481 self.assertEqual(copy2['name'], name)
481 self.assertEqual(copy2['name'], name)
482 self.assertEqual(copy2['path'], name)
482 self.assertEqual(copy2['path'], name)
483
483
484 def test_trust_notebook(self):
484 def test_trust_notebook(self):
485 cm = self.contents_manager
485 cm = self.contents_manager
486 nb, name, path = self.new_notebook()
486 nb, name, path = self.new_notebook()
487
487
488 untrusted = cm.get(path)['content']
488 untrusted = cm.get(path)['content']
489 assert not cm.notary.check_cells(untrusted)
489 assert not cm.notary.check_cells(untrusted)
490
490
491 # print(untrusted)
491 # print(untrusted)
492 cm.trust_notebook(path)
492 cm.trust_notebook(path)
493 trusted = cm.get(path)['content']
493 trusted = cm.get(path)['content']
494 # print(trusted)
494 # print(trusted)
495 assert cm.notary.check_cells(trusted)
495 assert cm.notary.check_cells(trusted)
496
496
497 def test_mark_trusted_cells(self):
497 def test_mark_trusted_cells(self):
498 cm = self.contents_manager
498 cm = self.contents_manager
499 nb, name, path = self.new_notebook()
499 nb, name, path = self.new_notebook()
500
500
501 cm.mark_trusted_cells(nb, path)
501 cm.mark_trusted_cells(nb, path)
502 for cell in nb.cells:
502 for cell in nb.cells:
503 if cell.cell_type == 'code':
503 if cell.cell_type == 'code':
504 assert not cell.metadata.trusted
504 assert not cell.metadata.trusted
505
505
506 cm.trust_notebook(path)
506 cm.trust_notebook(path)
507 nb = cm.get(path)['content']
507 nb = cm.get(path)['content']
508 for cell in nb.cells:
508 for cell in nb.cells:
509 if cell.cell_type == 'code':
509 if cell.cell_type == 'code':
510 assert cell.metadata.trusted
510 assert cell.metadata.trusted
511
511
512 def test_check_and_sign(self):
512 def test_check_and_sign(self):
513 cm = self.contents_manager
513 cm = self.contents_manager
514 nb, name, path = self.new_notebook()
514 nb, name, path = self.new_notebook()
515
515
516 cm.mark_trusted_cells(nb, path)
516 cm.mark_trusted_cells(nb, path)
517 cm.check_and_sign(nb, path)
517 cm.check_and_sign(nb, path)
518 assert not cm.notary.check_signature(nb)
518 assert not cm.notary.check_signature(nb)
519
519
520 cm.trust_notebook(path)
520 cm.trust_notebook(path)
521 nb = cm.get(path)['content']
521 nb = cm.get(path)['content']
522 cm.mark_trusted_cells(nb, path)
522 cm.mark_trusted_cells(nb, path)
523 cm.check_and_sign(nb, path)
523 cm.check_and_sign(nb, path)
524 assert cm.notary.check_signature(nb)
524 assert cm.notary.check_signature(nb)
General Comments 0
You need to be logged in to leave comments. Login now