test_manager.py
334 lines
| 11.4 KiB
| text/x-python
|
PythonLexer
MinRK
|
r13136 | # coding: utf-8 | ||
MinRK
|
r7637 | """Tests for the notebook manager.""" | ||
Thomas Kluyver
|
r13348 | from __future__ import print_function | ||
MinRK
|
r7637 | |||
MinRK
|
r15655 | import logging | ||
MinRK
|
r7637 | import os | ||
Zachary Sailer
|
r13046 | |||
from tornado.web import HTTPError | ||||
MinRK
|
r7637 | from unittest import TestCase | ||
from tempfile import NamedTemporaryFile | ||||
MinRK
|
r15655 | from IPython.nbformat import current | ||
MinRK
|
r7637 | from IPython.utils.tempdir import TemporaryDirectory | ||
from IPython.utils.traitlets import TraitError | ||||
Zachary Sailer
|
r13046 | from IPython.html.utils import url_path_join | ||
MinRK
|
r17710 | from IPython.testing import decorators as dec | ||
MinRK
|
r7637 | |||
MinRK
|
r17524 | from ..filemanager import FileContentsManager | ||
from ..manager import ContentsManager | ||||
MinRK
|
r7637 | |||
Brian E. Granger
|
r15079 | |||
MinRK
|
r17524 | class TestFileContentsManager(TestCase): | ||
MinRK
|
r7637 | |||
MinRK
|
r17524 | def test_root_dir(self): | ||
MinRK
|
r7637 | with TemporaryDirectory() as td: | ||
MinRK
|
r17524 | fm = FileContentsManager(root_dir=td) | ||
self.assertEqual(fm.root_dir, td) | ||||
MinRK
|
r7637 | |||
MinRK
|
r17524 | def test_missing_root_dir(self): | ||
MinRK
|
r7637 | with TemporaryDirectory() as td: | ||
MinRK
|
r17524 | root = os.path.join(td, 'notebook', 'dir', 'is', 'missing') | ||
self.assertRaises(TraitError, FileContentsManager, root_dir=root) | ||||
MinRK
|
r7637 | |||
MinRK
|
r17524 | def test_invalid_root_dir(self): | ||
MinRK
|
r7637 | with NamedTemporaryFile() as tf: | ||
MinRK
|
r17524 | self.assertRaises(TraitError, FileContentsManager, root_dir=tf.name) | ||
MinRK
|
r7637 | |||
Zachary Sailer
|
r13032 | def test_get_os_path(self): | ||
# full filesystem path should be returned with correct operating system | ||||
# separators. | ||||
with TemporaryDirectory() as td: | ||||
MinRK
|
r17524 | root = td | ||
fm = FileContentsManager(root_dir=root) | ||||
MinRK
|
r15420 | path = fm._get_os_path('test.ipynb', '/path/to/notebook/') | ||
Paul Ivanov
|
r13034 | rel_path_list = '/path/to/notebook/test.ipynb'.split('/') | ||
MinRK
|
r17524 | fs_path = os.path.join(fm.root_dir, *rel_path_list) | ||
Paul Ivanov
|
r13034 | self.assertEqual(path, fs_path) | ||
MinRK
|
r17524 | fm = FileContentsManager(root_dir=root) | ||
MinRK
|
r15420 | path = fm._get_os_path('test.ipynb') | ||
MinRK
|
r17524 | fs_path = os.path.join(fm.root_dir, 'test.ipynb') | ||
Paul Ivanov
|
r13034 | self.assertEqual(path, fs_path) | ||
MinRK
|
r17524 | fm = FileContentsManager(root_dir=root) | ||
MinRK
|
r15420 | path = fm._get_os_path('test.ipynb', '////') | ||
MinRK
|
r17524 | fs_path = os.path.join(fm.root_dir, 'test.ipynb') | ||
Paul Ivanov
|
r13034 | self.assertEqual(path, fs_path) | ||
MinRK
|
r17523 | |||
MinRK
|
r16440 | def test_checkpoint_subdir(self): | ||
subd = u'sub ∂ir' | ||||
cp_name = 'test-cp.ipynb' | ||||
with TemporaryDirectory() as td: | ||||
MinRK
|
r17524 | root = td | ||
MinRK
|
r16440 | os.mkdir(os.path.join(td, subd)) | ||
MinRK
|
r17524 | fm = FileContentsManager(root_dir=root) | ||
MinRK
|
r16440 | cp_dir = fm.get_checkpoint_path('cp', 'test.ipynb', '/') | ||
cp_subdir = fm.get_checkpoint_path('cp', 'test.ipynb', '/%s/' % subd) | ||||
self.assertNotEqual(cp_dir, cp_subdir) | ||||
MinRK
|
r17524 | self.assertEqual(cp_dir, os.path.join(root, fm.checkpoint_dir, cp_name)) | ||
self.assertEqual(cp_subdir, os.path.join(root, subd, fm.checkpoint_dir, cp_name)) | ||||
MinRK
|
r17523 | |||
Zachary Sailer
|
r13032 | |||
MinRK
|
r17525 | class TestContentsManager(TestCase): | ||
MinRK
|
r17523 | |||
MinRK
|
r15655 | def setUp(self): | ||
self._temp_dir = TemporaryDirectory() | ||||
self.td = self._temp_dir.name | ||||
MinRK
|
r17524 | self.contents_manager = FileContentsManager( | ||
root_dir=self.td, | ||||
MinRK
|
r15656 | log=logging.getLogger() | ||
) | ||||
MinRK
|
r17523 | |||
MinRK
|
r15655 | def tearDown(self): | ||
self._temp_dir.cleanup() | ||||
MinRK
|
r17523 | |||
Zachary Sailer
|
r13046 | def make_dir(self, abs_path, rel_path): | ||
"""make subdirectory, rel_path is the relative path | ||||
to that directory from the location where the server started""" | ||||
os_path = os.path.join(abs_path, rel_path) | ||||
try: | ||||
os.makedirs(os_path) | ||||
except OSError: | ||||
Brian E. Granger
|
r15080 | print("Directory already exists: %r" % os_path) | ||
MinRK
|
r17710 | return os_path | ||
MinRK
|
r17523 | |||
MinRK
|
r15655 | def add_code_cell(self, nb): | ||
output = current.new_output("display_data", output_javascript="alert('hi');") | ||||
cell = current.new_code_cell("print('hi')", outputs=[output]) | ||||
if not nb.worksheets: | ||||
nb.worksheets.append(current.new_worksheet()) | ||||
nb.worksheets[0].cells.append(cell) | ||||
MinRK
|
r17523 | |||
MinRK
|
r15655 | def new_notebook(self): | ||
MinRK
|
r17524 | cm = self.contents_manager | ||
MinRK
|
r17527 | model = cm.create_file() | ||
MinRK
|
r15655 | name = model['name'] | ||
path = model['path'] | ||||
MinRK
|
r17523 | |||
MinRK
|
r17525 | full_model = cm.get_model(name, path) | ||
MinRK
|
r15655 | nb = full_model['content'] | ||
self.add_code_cell(nb) | ||||
MinRK
|
r17523 | |||
MinRK
|
r17524 | cm.save(full_model, name, path) | ||
MinRK
|
r15655 | return nb, name, path | ||
MinRK
|
r17523 | |||
MinRK
|
r17527 | def test_create_file(self): | ||
MinRK
|
r17524 | cm = self.contents_manager | ||
MinRK
|
r15656 | # Test in root directory | ||
MinRK
|
r17527 | model = cm.create_file() | ||
MinRK
|
r15656 | assert isinstance(model, dict) | ||
self.assertIn('name', model) | ||||
self.assertIn('path', model) | ||||
self.assertEqual(model['name'], 'Untitled0.ipynb') | ||||
self.assertEqual(model['path'], '') | ||||
# Test in sub-directory | ||||
sub_dir = '/foo/' | ||||
MinRK
|
r17524 | self.make_dir(cm.root_dir, 'foo') | ||
MinRK
|
r17527 | model = cm.create_file(None, sub_dir) | ||
MinRK
|
r15656 | assert isinstance(model, dict) | ||
self.assertIn('name', model) | ||||
self.assertIn('path', model) | ||||
self.assertEqual(model['name'], 'Untitled0.ipynb') | ||||
self.assertEqual(model['path'], sub_dir.strip('/')) | ||||
Zachary Sailer
|
r13046 | |||
MinRK
|
r17524 | def test_get(self): | ||
cm = self.contents_manager | ||||
MinRK
|
r15656 | # Create a notebook | ||
MinRK
|
r17527 | model = cm.create_file() | ||
MinRK
|
r15656 | name = model['name'] | ||
path = model['path'] | ||||
# Check that we 'get' on the notebook we just created | ||||
MinRK
|
r17525 | model2 = cm.get_model(name, path) | ||
MinRK
|
r15656 | assert isinstance(model2, dict) | ||
self.assertIn('name', model2) | ||||
self.assertIn('path', model2) | ||||
self.assertEqual(model['name'], name) | ||||
self.assertEqual(model['path'], path) | ||||
# Test in sub-directory | ||||
sub_dir = '/foo/' | ||||
MinRK
|
r17524 | self.make_dir(cm.root_dir, 'foo') | ||
MinRK
|
r17527 | model = cm.create_file(None, sub_dir) | ||
MinRK
|
r17525 | model2 = cm.get_model(name, sub_dir) | ||
MinRK
|
r15656 | assert isinstance(model2, dict) | ||
self.assertIn('name', model2) | ||||
self.assertIn('path', model2) | ||||
self.assertIn('content', model2) | ||||
self.assertEqual(model2['name'], 'Untitled0.ipynb') | ||||
self.assertEqual(model2['path'], sub_dir.strip('/')) | ||||
MinRK
|
r17710 | |||
@dec.skip_win32 | ||||
def test_bad_symlink(self): | ||||
cm = self.contents_manager | ||||
path = 'test bad symlink' | ||||
os_path = self.make_dir(cm.root_dir, path) | ||||
file_model = cm.create_file(path=path, ext='.txt') | ||||
# create a broken symlink | ||||
os.symlink("target", os.path.join(os_path, "bad symlink")) | ||||
model = cm.get_model(path) | ||||
self.assertEqual(model['content'], [file_model]) | ||||
@dec.skip_win32 | ||||
def test_good_symlink(self): | ||||
cm = self.contents_manager | ||||
path = 'test good symlink' | ||||
os_path = self.make_dir(cm.root_dir, path) | ||||
file_model = cm.create_file(path=path, ext='.txt') | ||||
# create a good symlink | ||||
os.symlink(file_model['name'], os.path.join(os_path, "good symlink")) | ||||
symlink_model = cm.get_model(name="good symlink", path=path, content=False) | ||||
dir_model = cm.get_model(path) | ||||
self.assertEqual( | ||||
Thomas Kluyver
|
r17787 | sorted(dir_model['content'], key=lambda x: x['name']), | ||
MinRK
|
r17710 | [symlink_model, file_model], | ||
) | ||||
MinRK
|
r17524 | def test_update(self): | ||
cm = self.contents_manager | ||||
MinRK
|
r15656 | # Create a notebook | ||
MinRK
|
r17527 | model = cm.create_file() | ||
MinRK
|
r15656 | name = model['name'] | ||
path = model['path'] | ||||
# Change the name in the model for rename | ||||
model['name'] = 'test.ipynb' | ||||
MinRK
|
r17524 | model = cm.update(model, name, path) | ||
MinRK
|
r15656 | assert isinstance(model, dict) | ||
self.assertIn('name', model) | ||||
self.assertIn('path', model) | ||||
self.assertEqual(model['name'], 'test.ipynb') | ||||
# Make sure the old name is gone | ||||
MinRK
|
r17525 | self.assertRaises(HTTPError, cm.get_model, name, path) | ||
MinRK
|
r15656 | |||
# Test in sub-directory | ||||
# Create a directory and notebook in that directory | ||||
sub_dir = '/foo/' | ||||
MinRK
|
r17524 | self.make_dir(cm.root_dir, 'foo') | ||
MinRK
|
r17527 | model = cm.create_file(None, sub_dir) | ||
MinRK
|
r15656 | name = model['name'] | ||
path = model['path'] | ||||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # Change the name in the model for rename | ||
model['name'] = 'test_in_sub.ipynb' | ||||
MinRK
|
r17524 | model = cm.update(model, name, path) | ||
MinRK
|
r15656 | assert isinstance(model, dict) | ||
self.assertIn('name', model) | ||||
self.assertIn('path', model) | ||||
self.assertEqual(model['name'], 'test_in_sub.ipynb') | ||||
self.assertEqual(model['path'], sub_dir.strip('/')) | ||||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # Make sure the old name is gone | ||
MinRK
|
r17525 | self.assertRaises(HTTPError, cm.get_model, name, path) | ||
Zachary Sailer
|
r13046 | |||
MinRK
|
r17524 | def test_save(self): | ||
cm = self.contents_manager | ||||
MinRK
|
r15656 | # Create a notebook | ||
MinRK
|
r17527 | model = cm.create_file() | ||
MinRK
|
r15656 | name = model['name'] | ||
path = model['path'] | ||||
# Get the model with 'content' | ||||
MinRK
|
r17525 | full_model = cm.get_model(name, path) | ||
MinRK
|
r15656 | |||
# Save the notebook | ||||
MinRK
|
r17524 | model = cm.save(full_model, name, path) | ||
MinRK
|
r15656 | assert isinstance(model, dict) | ||
self.assertIn('name', model) | ||||
self.assertIn('path', model) | ||||
self.assertEqual(model['name'], name) | ||||
self.assertEqual(model['path'], path) | ||||
# Test in sub-directory | ||||
# Create a directory and notebook in that directory | ||||
sub_dir = '/foo/' | ||||
MinRK
|
r17524 | self.make_dir(cm.root_dir, 'foo') | ||
MinRK
|
r17527 | model = cm.create_file(None, sub_dir) | ||
MinRK
|
r15656 | name = model['name'] | ||
path = model['path'] | ||||
MinRK
|
r17525 | model = cm.get_model(name, path) | ||
MinRK
|
r15656 | |||
# Change the name in the model for rename | ||||
MinRK
|
r17524 | model = cm.save(model, name, path) | ||
MinRK
|
r15656 | assert isinstance(model, dict) | ||
self.assertIn('name', model) | ||||
self.assertIn('path', model) | ||||
self.assertEqual(model['name'], 'Untitled0.ipynb') | ||||
self.assertEqual(model['path'], sub_dir.strip('/')) | ||||
Zachary Sailer
|
r13046 | |||
MinRK
|
r17524 | def test_delete(self): | ||
cm = self.contents_manager | ||||
MinRK
|
r15656 | # Create a notebook | ||
nb, name, path = self.new_notebook() | ||||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # Delete the notebook | ||
MinRK
|
r17524 | cm.delete(name, path) | ||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # Check that a 'get' on the deleted notebook raises and error | ||
MinRK
|
r17525 | self.assertRaises(HTTPError, cm.get_model, name, path) | ||
MinRK
|
r17523 | |||
MinRK
|
r17524 | def test_copy(self): | ||
cm = self.contents_manager | ||||
MinRK
|
r15656 | path = u'Ã¥ b' | ||
name = u'nb √.ipynb' | ||||
MinRK
|
r17524 | os.mkdir(os.path.join(cm.root_dir, path)) | ||
MinRK
|
r17527 | orig = cm.create_file({'name' : name}, path=path) | ||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # copy with unspecified name | ||
MinRK
|
r17524 | copy = cm.copy(name, path=path) | ||
MinRK
|
r15656 | self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb')) | ||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # copy with specified name | ||
MinRK
|
r17524 | copy2 = cm.copy(name, u'copy 2.ipynb', path=path) | ||
MinRK
|
r15656 | self.assertEqual(copy2['name'], u'copy 2.ipynb') | ||
MinRK
|
r17523 | |||
MinRK
|
r15655 | def test_trust_notebook(self): | ||
MinRK
|
r17524 | cm = self.contents_manager | ||
MinRK
|
r15655 | nb, name, path = self.new_notebook() | ||
MinRK
|
r17523 | |||
MinRK
|
r17525 | untrusted = cm.get_model(name, path)['content'] | ||
MinRK
|
r17524 | assert not cm.notary.check_cells(untrusted) | ||
MinRK
|
r17523 | |||
MinRK
|
r15656 | # print(untrusted) | ||
MinRK
|
r17524 | cm.trust_notebook(name, path) | ||
MinRK
|
r17525 | trusted = cm.get_model(name, path)['content'] | ||
MinRK
|
r15656 | # print(trusted) | ||
MinRK
|
r17524 | assert cm.notary.check_cells(trusted) | ||
MinRK
|
r17523 | |||
MinRK
|
r15655 | def test_mark_trusted_cells(self): | ||
MinRK
|
r17524 | cm = self.contents_manager | ||
MinRK
|
r15655 | nb, name, path = self.new_notebook() | ||
MinRK
|
r17523 | |||
MinRK
|
r17524 | cm.mark_trusted_cells(nb, name, path) | ||
MinRK
|
r15655 | for cell in nb.worksheets[0].cells: | ||
if cell.cell_type == 'code': | ||||
MinRK
|
r18255 | assert not cell.metadata.trusted | ||
MinRK
|
r17523 | |||
MinRK
|
r17524 | cm.trust_notebook(name, path) | ||
MinRK
|
r17525 | nb = cm.get_model(name, path)['content'] | ||
MinRK
|
r15655 | for cell in nb.worksheets[0].cells: | ||
if cell.cell_type == 'code': | ||||
MinRK
|
r18255 | assert cell.metadata.trusted | ||
MinRK
|
r15655 | |||
def test_check_and_sign(self): | ||||
MinRK
|
r17524 | cm = self.contents_manager | ||
MinRK
|
r15655 | nb, name, path = self.new_notebook() | ||
MinRK
|
r17523 | |||
MinRK
|
r17524 | cm.mark_trusted_cells(nb, name, path) | ||
cm.check_and_sign(nb, name, path) | ||||
assert not cm.notary.check_signature(nb) | ||||
MinRK
|
r17523 | |||
MinRK
|
r17524 | cm.trust_notebook(name, path) | ||
MinRK
|
r17525 | nb = cm.get_model(name, path)['content'] | ||
MinRK
|
r17524 | cm.mark_trusted_cells(nb, name, path) | ||
cm.check_and_sign(nb, name, path) | ||||
assert cm.notary.check_signature(nb) | ||||