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