mirror of
https://github.com/jupyter/notebook.git
synced 2024-12-21 04:10:17 +08:00
mv services/notebooks services/contents
This commit is contained in:
parent
6d292040b4
commit
b73aa2b9f9
@ -27,10 +27,10 @@ def sort_key(item):
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class FileNotebookManager(NotebookManager):
|
||||
|
||||
|
||||
save_script = Bool(False, config=True,
|
||||
help="""Automatically create a Python script when saving the notebook.
|
||||
|
||||
|
||||
For easier use of import, %run and %load across notebooks, a
|
||||
<notebook-name>.py script will be created next to any
|
||||
<notebook-name>.ipynb on each save. This can also be set with the
|
||||
@ -38,7 +38,7 @@ class FileNotebookManager(NotebookManager):
|
||||
"""
|
||||
)
|
||||
notebook_dir = Unicode(getcwd(), config=True)
|
||||
|
||||
|
||||
def _notebook_dir_changed(self, name, old, new):
|
||||
"""Do a bit of validation of the notebook dir."""
|
||||
if not os.path.isabs(new):
|
||||
@ -47,19 +47,19 @@ class FileNotebookManager(NotebookManager):
|
||||
return
|
||||
if not os.path.exists(new) or not os.path.isdir(new):
|
||||
raise TraitError("notebook dir %r is not a directory" % new)
|
||||
|
||||
|
||||
checkpoint_dir = Unicode('.ipynb_checkpoints', config=True,
|
||||
help="""The directory name in which to keep notebook checkpoints
|
||||
|
||||
|
||||
This is a path relative to the notebook's own directory.
|
||||
|
||||
|
||||
By default, it is .ipynb_checkpoints
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def _copy(self, src, dest):
|
||||
"""copy src to dest
|
||||
|
||||
|
||||
like shutil.copy2, but log errors in copystat
|
||||
"""
|
||||
shutil.copyfile(src, dest)
|
||||
@ -67,7 +67,7 @@ class FileNotebookManager(NotebookManager):
|
||||
shutil.copystat(src, dest)
|
||||
except OSError as e:
|
||||
self.log.debug("copystat on %s failed", dest, exc_info=True)
|
||||
|
||||
|
||||
def get_notebook_names(self, path=''):
|
||||
"""List all notebook names in the notebook dir and path."""
|
||||
path = path.strip('/')
|
||||
@ -80,13 +80,13 @@ class FileNotebookManager(NotebookManager):
|
||||
|
||||
def path_exists(self, path):
|
||||
"""Does the API-style path (directory) actually exist?
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path : string
|
||||
The path to check. This is an API path (`/` separated,
|
||||
relative to base notebook-dir).
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
exists : bool
|
||||
@ -98,18 +98,18 @@ class FileNotebookManager(NotebookManager):
|
||||
|
||||
def is_hidden(self, path):
|
||||
"""Does the API style path correspond to a hidden directory or file?
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path : string
|
||||
The path to check. This is an API path (`/` separated,
|
||||
relative to base notebook-dir).
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
exists : bool
|
||||
Whether the path is hidden.
|
||||
|
||||
|
||||
"""
|
||||
path = path.strip('/')
|
||||
os_path = self._get_os_path(path=path)
|
||||
@ -204,13 +204,13 @@ class FileNotebookManager(NotebookManager):
|
||||
def list_notebooks(self, path):
|
||||
"""Returns a list of dictionaries that are the standard model
|
||||
for all notebooks in the relative 'path'.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path : str
|
||||
the URL path that describes the relative path for the
|
||||
listed notebooks
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
notebooks : list of dicts
|
||||
@ -225,7 +225,7 @@ class FileNotebookManager(NotebookManager):
|
||||
|
||||
def get_notebook(self, name, path='', content=True):
|
||||
""" Takes a path and name for a notebook and returns its model
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
@ -233,11 +233,11 @@ class FileNotebookManager(NotebookManager):
|
||||
path : str
|
||||
the URL path that describes the relative path for
|
||||
the notebook
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
model : dict
|
||||
the notebook model. If contents=True, returns the 'contents'
|
||||
the notebook model. If contents=True, returns the 'contents'
|
||||
dict in the model as well.
|
||||
"""
|
||||
path = path.strip('/')
|
||||
@ -284,9 +284,9 @@ class FileNotebookManager(NotebookManager):
|
||||
# Save the notebook file
|
||||
os_path = self._get_os_path(new_name, new_path)
|
||||
nb = current.to_notebook_json(model['content'])
|
||||
|
||||
|
||||
self.check_and_sign(nb, new_name, new_path)
|
||||
|
||||
|
||||
if 'name' in nb['metadata']:
|
||||
nb['metadata']['name'] = u''
|
||||
try:
|
||||
@ -325,7 +325,7 @@ class FileNotebookManager(NotebookManager):
|
||||
os_path = self._get_os_path(name, path)
|
||||
if not os.path.isfile(os_path):
|
||||
raise web.HTTPError(404, u'Notebook does not exist: %s' % os_path)
|
||||
|
||||
|
||||
# clear checkpoints
|
||||
for checkpoint in self.list_checkpoints(name, path):
|
||||
checkpoint_id = checkpoint['id']
|
||||
@ -333,7 +333,7 @@ class FileNotebookManager(NotebookManager):
|
||||
if os.path.isfile(cp_path):
|
||||
self.log.debug("Unlinking checkpoint %s", cp_path)
|
||||
os.unlink(cp_path)
|
||||
|
||||
|
||||
self.log.debug("Unlinking notebook %s", os_path)
|
||||
os.unlink(os_path)
|
||||
|
||||
@ -343,7 +343,7 @@ class FileNotebookManager(NotebookManager):
|
||||
new_path = new_path.strip('/')
|
||||
if new_name == old_name and new_path == old_path:
|
||||
return
|
||||
|
||||
|
||||
new_os_path = self._get_os_path(new_name, new_path)
|
||||
old_os_path = self._get_os_path(old_name, old_path)
|
||||
|
||||
@ -375,9 +375,9 @@ class FileNotebookManager(NotebookManager):
|
||||
# Move the .py script
|
||||
if self.save_script:
|
||||
shutil.move(old_py_path, new_py_path)
|
||||
|
||||
|
||||
# Checkpoint-related utilities
|
||||
|
||||
|
||||
def get_checkpoint_path(self, checkpoint_id, name, path=''):
|
||||
"""find the path to a checkpoint"""
|
||||
path = path.strip('/')
|
||||
@ -404,9 +404,9 @@ class FileNotebookManager(NotebookManager):
|
||||
last_modified = last_modified,
|
||||
)
|
||||
return info
|
||||
|
||||
|
||||
# public checkpoint API
|
||||
|
||||
|
||||
def create_checkpoint(self, name, path=''):
|
||||
"""Create a checkpoint from the current state of a notebook"""
|
||||
path = path.strip('/')
|
||||
@ -416,13 +416,13 @@ class FileNotebookManager(NotebookManager):
|
||||
cp_path = self.get_checkpoint_path(checkpoint_id, name, path)
|
||||
self.log.debug("creating checkpoint for notebook %s", name)
|
||||
self._copy(nb_path, cp_path)
|
||||
|
||||
|
||||
# return the checkpoint info
|
||||
return self.get_checkpoint_model(checkpoint_id, name, path)
|
||||
|
||||
|
||||
def list_checkpoints(self, name, path=''):
|
||||
"""list the checkpoints for a given notebook
|
||||
|
||||
|
||||
This notebook manager currently only supports one checkpoint per notebook.
|
||||
"""
|
||||
path = path.strip('/')
|
||||
@ -432,8 +432,8 @@ class FileNotebookManager(NotebookManager):
|
||||
return []
|
||||
else:
|
||||
return [self.get_checkpoint_model(checkpoint_id, name, path)]
|
||||
|
||||
|
||||
|
||||
|
||||
def restore_checkpoint(self, checkpoint_id, name, path=''):
|
||||
"""restore a notebook to a checkpointed state"""
|
||||
path = path.strip('/')
|
||||
@ -450,7 +450,7 @@ class FileNotebookManager(NotebookManager):
|
||||
current.read(f, u'json')
|
||||
self._copy(cp_path, nb_path)
|
||||
self.log.debug("copying %s -> %s", cp_path, nb_path)
|
||||
|
||||
|
||||
def delete_checkpoint(self, checkpoint_id, name, path=''):
|
||||
"""delete a notebook's checkpoint"""
|
||||
path = path.strip('/')
|
||||
@ -461,7 +461,7 @@ class FileNotebookManager(NotebookManager):
|
||||
)
|
||||
self.log.debug("unlinking %s", cp_path)
|
||||
os.unlink(cp_path)
|
||||
|
||||
|
||||
def info_string(self):
|
||||
return "Serving notebooks from local directory: %s" % self.notebook_dir
|
||||
|
@ -38,7 +38,7 @@ class NotebookHandler(IPythonHandler):
|
||||
|
||||
def notebook_location(self, name, path=''):
|
||||
"""Return the full URL location of a notebook based.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : unicode
|
||||
@ -57,7 +57,7 @@ class NotebookHandler(IPythonHandler):
|
||||
self.set_header('Location', location)
|
||||
self.set_header('Last-Modified', model['last_modified'])
|
||||
self.finish(json.dumps(model, default=date_default))
|
||||
|
||||
|
||||
@web.authenticated
|
||||
@json_errors
|
||||
def get(self, path='', name=None):
|
||||
@ -99,10 +99,10 @@ class NotebookHandler(IPythonHandler):
|
||||
raise web.HTTPError(400, u'JSON body missing')
|
||||
model = nbm.update_notebook(model, name, path)
|
||||
self._finish_model(model)
|
||||
|
||||
|
||||
def _copy_notebook(self, copy_from, path, copy_to=None):
|
||||
"""Copy a notebook in path, optionally specifying the new name.
|
||||
|
||||
|
||||
Only support copying within the same directory.
|
||||
"""
|
||||
self.log.info(u"Copying notebook from %s/%s to %s/%s",
|
||||
@ -112,23 +112,23 @@ class NotebookHandler(IPythonHandler):
|
||||
model = self.notebook_manager.copy_notebook(copy_from, copy_to, path)
|
||||
self.set_status(201)
|
||||
self._finish_model(model)
|
||||
|
||||
|
||||
def _upload_notebook(self, model, path, name=None):
|
||||
"""Upload a notebook
|
||||
|
||||
|
||||
If name specified, create it in path/name.
|
||||
"""
|
||||
self.log.info(u"Uploading notebook to %s/%s", path, name or '')
|
||||
if name:
|
||||
model['name'] = name
|
||||
|
||||
|
||||
model = self.notebook_manager.create_notebook(model, path)
|
||||
self.set_status(201)
|
||||
self._finish_model(model)
|
||||
|
||||
|
||||
def _create_empty_notebook(self, path, name=None):
|
||||
"""Create an empty notebook in path
|
||||
|
||||
|
||||
If name specified, create it in path/name.
|
||||
"""
|
||||
self.log.info(u"Creating new notebook in %s/%s", path, name or '')
|
||||
@ -138,7 +138,7 @@ class NotebookHandler(IPythonHandler):
|
||||
model = self.notebook_manager.create_notebook(model, path=path)
|
||||
self.set_status(201)
|
||||
self._finish_model(model)
|
||||
|
||||
|
||||
def _save_notebook(self, model, path, name):
|
||||
"""Save an existing notebook."""
|
||||
self.log.info(u"Saving notebook at %s/%s", path, name)
|
||||
@ -149,26 +149,26 @@ class NotebookHandler(IPythonHandler):
|
||||
else:
|
||||
location = False
|
||||
self._finish_model(model, location)
|
||||
|
||||
|
||||
@web.authenticated
|
||||
@json_errors
|
||||
def post(self, path='', name=None):
|
||||
"""Create a new notebook in the specified path.
|
||||
|
||||
|
||||
POST creates new notebooks. The server always decides on the notebook name.
|
||||
|
||||
|
||||
POST /api/notebooks/path
|
||||
New untitled notebook in path. If content specified, upload a
|
||||
notebook, otherwise start empty.
|
||||
POST /api/notebooks/path?copy=OtherNotebook.ipynb
|
||||
New copy of OtherNotebook in path
|
||||
"""
|
||||
|
||||
|
||||
if name is not None:
|
||||
raise web.HTTPError(400, "Only POST to directories. Use PUT for full names.")
|
||||
|
||||
|
||||
model = self.get_json_body()
|
||||
|
||||
|
||||
if model is not None:
|
||||
copy_from = model.get('copy_from')
|
||||
if copy_from:
|
||||
@ -184,10 +184,10 @@ class NotebookHandler(IPythonHandler):
|
||||
@json_errors
|
||||
def put(self, path='', name=None):
|
||||
"""Saves the notebook in the location specified by name and path.
|
||||
|
||||
|
||||
PUT is very similar to POST, but the requester specifies the name,
|
||||
whereas with POST, the server picks the name.
|
||||
|
||||
|
||||
PUT /api/notebooks/path/Name.ipynb
|
||||
Save notebook at ``path/Name.ipynb``. Notebook structure is specified
|
||||
in `content` key of JSON request body. If content is not specified,
|
||||
@ -197,7 +197,7 @@ class NotebookHandler(IPythonHandler):
|
||||
"""
|
||||
if name is None:
|
||||
raise web.HTTPError(400, "Only PUT to full names. Use POST for directories.")
|
||||
|
||||
|
||||
model = self.get_json_body()
|
||||
if model:
|
||||
copy_from = model.get('copy_from')
|
||||
@ -223,9 +223,9 @@ class NotebookHandler(IPythonHandler):
|
||||
|
||||
|
||||
class NotebookCheckpointsHandler(IPythonHandler):
|
||||
|
||||
|
||||
SUPPORTED_METHODS = ('GET', 'POST')
|
||||
|
||||
|
||||
@web.authenticated
|
||||
@json_errors
|
||||
def get(self, path='', name=None):
|
||||
@ -234,7 +234,7 @@ class NotebookCheckpointsHandler(IPythonHandler):
|
||||
checkpoints = nbm.list_checkpoints(name, path)
|
||||
data = json.dumps(checkpoints, default=date_default)
|
||||
self.finish(data)
|
||||
|
||||
|
||||
@web.authenticated
|
||||
@json_errors
|
||||
def post(self, path='', name=None):
|
||||
@ -250,9 +250,9 @@ class NotebookCheckpointsHandler(IPythonHandler):
|
||||
|
||||
|
||||
class ModifyNotebookCheckpointsHandler(IPythonHandler):
|
||||
|
||||
|
||||
SUPPORTED_METHODS = ('POST', 'DELETE')
|
||||
|
||||
|
||||
@web.authenticated
|
||||
@json_errors
|
||||
def post(self, path, name, checkpoint_id):
|
||||
@ -261,7 +261,7 @@ class ModifyNotebookCheckpointsHandler(IPythonHandler):
|
||||
nbm.restore_checkpoint(checkpoint_id, name, path)
|
||||
self.set_status(204)
|
||||
self.finish()
|
||||
|
||||
|
||||
@web.authenticated
|
||||
@json_errors
|
||||
def delete(self, path, name, checkpoint_id):
|
||||
@ -270,7 +270,7 @@ class ModifyNotebookCheckpointsHandler(IPythonHandler):
|
||||
nbm.delete_checkpoint(checkpoint_id, name, path)
|
||||
self.set_status(204)
|
||||
self.finish()
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# URL to handler mappings
|
||||
#-----------------------------------------------------------------------------
|
||||
@ -285,4 +285,3 @@ default_handlers = [
|
||||
(r"/api/notebooks%s" % notebook_path_regex, NotebookHandler),
|
||||
(r"/api/notebooks%s" % path_regex, NotebookHandler),
|
||||
]
|
||||
|
@ -32,11 +32,11 @@ from IPython.utils.traitlets import Instance, Unicode, List
|
||||
class NotebookManager(LoggingConfigurable):
|
||||
|
||||
filename_ext = Unicode(u'.ipynb')
|
||||
|
||||
|
||||
notary = Instance(sign.NotebookNotary)
|
||||
def _notary_default(self):
|
||||
return sign.NotebookNotary(parent=self)
|
||||
|
||||
|
||||
hide_globs = List(Unicode, [u'__pycache__'], config=True, help="""
|
||||
Glob patterns to hide in file and directory listings.
|
||||
""")
|
||||
@ -46,14 +46,14 @@ class NotebookManager(LoggingConfigurable):
|
||||
|
||||
def path_exists(self, path):
|
||||
"""Does the API-style path (directory) actually exist?
|
||||
|
||||
|
||||
Override this method in subclasses.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path : string
|
||||
The path to check
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
exists : bool
|
||||
@ -63,18 +63,18 @@ class NotebookManager(LoggingConfigurable):
|
||||
|
||||
def is_hidden(self, path):
|
||||
"""Does the API style path correspond to a hidden directory or file?
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path : string
|
||||
The path to check. This is an API path (`/` separated,
|
||||
relative to base notebook-dir).
|
||||
|
||||
|
||||
Returns
|
||||
-------
|
||||
exists : bool
|
||||
Whether the path is hidden.
|
||||
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@ -104,7 +104,7 @@ class NotebookManager(LoggingConfigurable):
|
||||
# no longer listed by the notebook web service.
|
||||
def get_dir_model(self, name, path=''):
|
||||
"""Get the directory model given a directory name and its API style path.
|
||||
|
||||
|
||||
The keys in the model should be:
|
||||
* name
|
||||
* path
|
||||
@ -145,15 +145,15 @@ class NotebookManager(LoggingConfigurable):
|
||||
|
||||
def create_checkpoint(self, name, path=''):
|
||||
"""Create a checkpoint of the current state of a notebook
|
||||
|
||||
|
||||
Returns a checkpoint_id for the new checkpoint.
|
||||
"""
|
||||
raise NotImplementedError("must be implemented in a subclass")
|
||||
|
||||
|
||||
def list_checkpoints(self, name, path=''):
|
||||
"""Return a list of checkpoints for a given notebook"""
|
||||
return []
|
||||
|
||||
|
||||
def restore_checkpoint(self, checkpoint_id, name, path=''):
|
||||
"""Restore a notebook from one of its checkpoints"""
|
||||
raise NotImplementedError("must be implemented in a subclass")
|
||||
@ -161,7 +161,7 @@ class NotebookManager(LoggingConfigurable):
|
||||
def delete_checkpoint(self, checkpoint_id, name, path=''):
|
||||
"""delete a checkpoint for a notebook"""
|
||||
raise NotImplementedError("must be implemented in a subclass")
|
||||
|
||||
|
||||
def info_string(self):
|
||||
return "Serving notebooks"
|
||||
|
||||
@ -174,7 +174,7 @@ class NotebookManager(LoggingConfigurable):
|
||||
|
||||
def increment_filename(self, basename, path=''):
|
||||
"""Increment a notebook filename without the .ipynb to make it unique.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
basename : unicode
|
||||
@ -206,14 +206,14 @@ class NotebookManager(LoggingConfigurable):
|
||||
model['content'] = current.new_notebook(metadata=metadata)
|
||||
if 'name' not in model:
|
||||
model['name'] = self.increment_filename('Untitled', path)
|
||||
|
||||
|
||||
model['path'] = path
|
||||
model = self.save_notebook(model, model['name'], model['path'])
|
||||
return model
|
||||
|
||||
def copy_notebook(self, from_name, to_name=None, path=''):
|
||||
"""Copy an existing notebook and return its new model.
|
||||
|
||||
|
||||
If to_name not specified, increment `from_name-Copy#.ipynb`.
|
||||
"""
|
||||
path = path.strip('/')
|
||||
@ -224,13 +224,13 @@ class NotebookManager(LoggingConfigurable):
|
||||
model['name'] = to_name
|
||||
model = self.save_notebook(model, to_name, path)
|
||||
return model
|
||||
|
||||
|
||||
def log_info(self):
|
||||
self.log.info(self.info_string())
|
||||
|
||||
def trust_notebook(self, name, path=''):
|
||||
"""Explicitly trust a notebook
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name : string
|
||||
@ -243,12 +243,12 @@ class NotebookManager(LoggingConfigurable):
|
||||
self.log.warn("Trusting notebook %s/%s", path, name)
|
||||
self.notary.mark_cells(nb, True)
|
||||
self.save_notebook(model, name, path)
|
||||
|
||||
|
||||
def check_and_sign(self, nb, name, path=''):
|
||||
"""Check for trusted cells, and sign the notebook.
|
||||
|
||||
|
||||
Called as a part of saving notebooks.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nb : dict
|
||||
@ -262,12 +262,12 @@ class NotebookManager(LoggingConfigurable):
|
||||
self.notary.sign(nb)
|
||||
else:
|
||||
self.log.warn("Saving untrusted notebook %s/%s", path, name)
|
||||
|
||||
|
||||
def mark_trusted_cells(self, nb, name, path=''):
|
||||
"""Mark cells as trusted if the notebook signature matches.
|
||||
|
||||
|
||||
Called as a part of loading notebooks.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nb : dict
|
@ -55,7 +55,7 @@ class TestFileNotebookManager(TestCase):
|
||||
path = fm._get_os_path('test.ipynb', '////')
|
||||
fs_path = os.path.join(fm.notebook_dir, 'test.ipynb')
|
||||
self.assertEqual(path, fs_path)
|
||||
|
||||
|
||||
def test_checkpoint_subdir(self):
|
||||
subd = u'sub ∂ir'
|
||||
cp_name = 'test-cp.ipynb'
|
||||
@ -68,10 +68,10 @@ class TestFileNotebookManager(TestCase):
|
||||
self.assertNotEqual(cp_dir, cp_subdir)
|
||||
self.assertEqual(cp_dir, os.path.join(nbdir, fm.checkpoint_dir, cp_name))
|
||||
self.assertEqual(cp_subdir, os.path.join(nbdir, subd, fm.checkpoint_dir, cp_name))
|
||||
|
||||
|
||||
|
||||
class TestNotebookManager(TestCase):
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self._temp_dir = TemporaryDirectory()
|
||||
self.td = self._temp_dir.name
|
||||
@ -79,10 +79,10 @@ class TestNotebookManager(TestCase):
|
||||
notebook_dir=self.td,
|
||||
log=logging.getLogger()
|
||||
)
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
self._temp_dir.cleanup()
|
||||
|
||||
|
||||
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"""
|
||||
@ -91,27 +91,27 @@ class TestNotebookManager(TestCase):
|
||||
os.makedirs(os_path)
|
||||
except OSError:
|
||||
print("Directory already exists: %r" % os_path)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def new_notebook(self):
|
||||
nbm = self.notebook_manager
|
||||
model = nbm.create_notebook()
|
||||
name = model['name']
|
||||
path = model['path']
|
||||
|
||||
|
||||
full_model = nbm.get_notebook(name, path)
|
||||
nb = full_model['content']
|
||||
self.add_code_cell(nb)
|
||||
|
||||
|
||||
nbm.save_notebook(full_model, name, path)
|
||||
return nb, name, path
|
||||
|
||||
|
||||
def test_create_notebook(self):
|
||||
nm = self.notebook_manager
|
||||
# Test in root directory
|
||||
@ -158,7 +158,7 @@ class TestNotebookManager(TestCase):
|
||||
self.assertIn('content', model2)
|
||||
self.assertEqual(model2['name'], 'Untitled0.ipynb')
|
||||
self.assertEqual(model2['path'], sub_dir.strip('/'))
|
||||
|
||||
|
||||
def test_update_notebook(self):
|
||||
nm = self.notebook_manager
|
||||
# Create a notebook
|
||||
@ -184,7 +184,7 @@ class TestNotebookManager(TestCase):
|
||||
model = nm.create_notebook(None, sub_dir)
|
||||
name = model['name']
|
||||
path = model['path']
|
||||
|
||||
|
||||
# Change the name in the model for rename
|
||||
model['name'] = 'test_in_sub.ipynb'
|
||||
model = nm.update_notebook(model, name, path)
|
||||
@ -193,7 +193,7 @@ class TestNotebookManager(TestCase):
|
||||
self.assertIn('path', model)
|
||||
self.assertEqual(model['name'], 'test_in_sub.ipynb')
|
||||
self.assertEqual(model['path'], sub_dir.strip('/'))
|
||||
|
||||
|
||||
# Make sure the old name is gone
|
||||
self.assertRaises(HTTPError, nm.get_notebook, name, path)
|
||||
|
||||
@ -255,50 +255,50 @@ class TestNotebookManager(TestCase):
|
||||
nm = self.notebook_manager
|
||||
# Create a notebook
|
||||
nb, name, path = self.new_notebook()
|
||||
|
||||
|
||||
# Delete the notebook
|
||||
nm.delete_notebook(name, path)
|
||||
|
||||
|
||||
# Check that a 'get' on the deleted notebook raises and error
|
||||
self.assertRaises(HTTPError, nm.get_notebook, name, path)
|
||||
|
||||
|
||||
def test_copy_notebook(self):
|
||||
nm = self.notebook_manager
|
||||
path = u'å b'
|
||||
name = u'nb √.ipynb'
|
||||
os.mkdir(os.path.join(nm.notebook_dir, path))
|
||||
orig = nm.create_notebook({'name' : name}, path=path)
|
||||
|
||||
|
||||
# copy with unspecified name
|
||||
copy = nm.copy_notebook(name, path=path)
|
||||
self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
|
||||
|
||||
|
||||
# copy with specified name
|
||||
copy2 = nm.copy_notebook(name, u'copy 2.ipynb', path=path)
|
||||
self.assertEqual(copy2['name'], u'copy 2.ipynb')
|
||||
|
||||
|
||||
def test_trust_notebook(self):
|
||||
nbm = self.notebook_manager
|
||||
nb, name, path = self.new_notebook()
|
||||
|
||||
|
||||
untrusted = nbm.get_notebook(name, path)['content']
|
||||
assert not nbm.notary.check_cells(untrusted)
|
||||
|
||||
|
||||
# print(untrusted)
|
||||
nbm.trust_notebook(name, path)
|
||||
trusted = nbm.get_notebook(name, path)['content']
|
||||
# print(trusted)
|
||||
assert nbm.notary.check_cells(trusted)
|
||||
|
||||
|
||||
def test_mark_trusted_cells(self):
|
||||
nbm = self.notebook_manager
|
||||
nb, name, path = self.new_notebook()
|
||||
|
||||
|
||||
nbm.mark_trusted_cells(nb, name, path)
|
||||
for cell in nb.worksheets[0].cells:
|
||||
if cell.cell_type == 'code':
|
||||
assert not cell.trusted
|
||||
|
||||
|
||||
nbm.trust_notebook(name, path)
|
||||
nb = nbm.get_notebook(name, path)['content']
|
||||
for cell in nb.worksheets[0].cells:
|
||||
@ -308,11 +308,11 @@ class TestNotebookManager(TestCase):
|
||||
def test_check_and_sign(self):
|
||||
nbm = self.notebook_manager
|
||||
nb, name, path = self.new_notebook()
|
||||
|
||||
|
||||
nbm.mark_trusted_cells(nb, name, path)
|
||||
nbm.check_and_sign(nb, name, path)
|
||||
assert not nbm.notary.check_signature(nb)
|
||||
|
||||
|
||||
nbm.trust_notebook(name, path)
|
||||
nb = nbm.get_notebook(name, path)['content']
|
||||
nbm.mark_trusted_cells(nb, name, path)
|
@ -163,7 +163,7 @@ class APITest(NotebookTestBase):
|
||||
expected = [ u'a.ipynb', u'b.ipynb', u'name with spaces.ipynb', u'unicodé.ipynb']
|
||||
expected = { normalize('NFC', name) for name in expected }
|
||||
self.assertEqual(nbnames, expected)
|
||||
|
||||
|
||||
nbs = notebooks_only(self.nb_api.list('ordering').json())
|
||||
nbnames = [n['name'] for n in nbs]
|
||||
expected = ['A.ipynb', 'b.ipynb', 'C.ipynb']
|
||||
@ -344,4 +344,3 @@ class APITest(NotebookTestBase):
|
||||
self.assertEqual(r.status_code, 204)
|
||||
cps = self.nb_api.get_checkpoints('a.ipynb', 'foo').json()
|
||||
self.assertEqual(cps, [])
|
||||
|
Loading…
Reference in New Issue
Block a user