mirror of
https://github.com/jupyter/notebook.git
synced 2025-02-05 12:19:58 +08:00
update upload and copy
adds 'notebook.ipynb/copy' url handler because we were putting too many things in a single POST handler.
This commit is contained in:
parent
75e14424c6
commit
b33ffa7068
@ -71,8 +71,7 @@ class NotebookHandler(IPythonHandler):
|
|||||||
@web.authenticated
|
@web.authenticated
|
||||||
@json_errors
|
@json_errors
|
||||||
def patch(self, path='', name=None):
|
def patch(self, path='', name=None):
|
||||||
"""patch is currently used strictly for notebook renaming.
|
"""PATCH renames a notebook without re-uploading content."""
|
||||||
Changes the notebook name to the name given in data."""
|
|
||||||
nbm = self.notebook_manager
|
nbm = self.notebook_manager
|
||||||
if name is None:
|
if name is None:
|
||||||
raise web.HTTPError(400, u'Notebook name missing')
|
raise web.HTTPError(400, u'Notebook name missing')
|
||||||
@ -90,10 +89,31 @@ class NotebookHandler(IPythonHandler):
|
|||||||
@web.authenticated
|
@web.authenticated
|
||||||
@json_errors
|
@json_errors
|
||||||
def post(self, path='', name=None):
|
def post(self, path='', name=None):
|
||||||
"""Create a new notebook in the location given by 'notebook_path'."""
|
"""Create a new notebook in the specified path.
|
||||||
|
|
||||||
|
POST creates new notebooks.
|
||||||
|
|
||||||
|
POST /api/notebooks/path : new untitled notebook in path
|
||||||
|
POST /api/notebooks/path/notebook.ipynb : new notebook with name in path
|
||||||
|
If content specified upload notebook, otherwise start empty.
|
||||||
|
"""
|
||||||
nbm = self.notebook_manager
|
nbm = self.notebook_manager
|
||||||
model = self.get_json_body()
|
model = self.get_json_body()
|
||||||
model = nbm.create_notebook_model(model, path)
|
if name is None:
|
||||||
|
# creating new notebook, model doesn't make sense
|
||||||
|
if model is not None:
|
||||||
|
raise web.HTTPError(400, "Model not valid when creating untitled notebooks.")
|
||||||
|
model = nbm.create_notebook_model(path=path)
|
||||||
|
else:
|
||||||
|
if model is None:
|
||||||
|
self.log.info("Creating new Notebook at %s/%s", path, name)
|
||||||
|
model = {}
|
||||||
|
else:
|
||||||
|
self.log.info("Uploading Notebook to %s/%s", path, name)
|
||||||
|
# set the model name from the URL
|
||||||
|
model['name'] = name
|
||||||
|
model = nbm.create_notebook_model(model, path)
|
||||||
|
|
||||||
location = self.notebook_location(model[u'name'], model[u'path'])
|
location = self.notebook_location(model[u'name'], model[u'path'])
|
||||||
self.set_header(u'Location', location)
|
self.set_header(u'Location', location)
|
||||||
self.set_header(u'Last-Modified', model[u'last_modified'])
|
self.set_header(u'Last-Modified', model[u'last_modified'])
|
||||||
@ -120,6 +140,29 @@ class NotebookHandler(IPythonHandler):
|
|||||||
self.set_status(204)
|
self.set_status(204)
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
|
class NotebookCopyHandler(IPythonHandler):
|
||||||
|
|
||||||
|
SUPPORTED_METHODS = ('POST')
|
||||||
|
|
||||||
|
@web.authenticated
|
||||||
|
@json_errors
|
||||||
|
def post(self, path='', name=None):
|
||||||
|
"""Copy an existing notebook."""
|
||||||
|
nbm = self.notebook_manager
|
||||||
|
model = self.get_json_body()
|
||||||
|
if name is None:
|
||||||
|
raise web.HTTPError(400, "Notebook name required")
|
||||||
|
self.log.info("Copying Notebook %s/%s", path, name)
|
||||||
|
model = nbm.copy_notebook(name, path)
|
||||||
|
location = url_path_join(
|
||||||
|
self.base_project_url, 'api', 'notebooks',
|
||||||
|
model['path'], model['name'],
|
||||||
|
)
|
||||||
|
self.set_header(u'Location', location)
|
||||||
|
self.set_header(u'Last-Modified', model[u'last_modified'])
|
||||||
|
self.set_status(201)
|
||||||
|
self.finish(json.dumps(model, default=date_default))
|
||||||
|
|
||||||
|
|
||||||
class NotebookCheckpointsHandler(IPythonHandler):
|
class NotebookCheckpointsHandler(IPythonHandler):
|
||||||
|
|
||||||
@ -180,6 +223,7 @@ _notebook_name_regex = r"(?P<name>[^/]+\.ipynb)"
|
|||||||
_notebook_path_regex = "%s/%s" % (_path_regex, _notebook_name_regex)
|
_notebook_path_regex = "%s/%s" % (_path_regex, _notebook_name_regex)
|
||||||
|
|
||||||
default_handlers = [
|
default_handlers = [
|
||||||
|
(r"/api/notebooks/?%s/copy" % _notebook_path_regex, NotebookCopyHandler),
|
||||||
(r"/api/notebooks/?%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
|
(r"/api/notebooks/?%s/checkpoints" % _notebook_path_regex, NotebookCheckpointsHandler),
|
||||||
(r"/api/notebooks/?%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
|
(r"/api/notebooks/?%s/checkpoints/%s" % (_notebook_path_regex, _checkpoint_id_regex),
|
||||||
ModifyNotebookCheckpointsHandler),
|
ModifyNotebookCheckpointsHandler),
|
||||||
|
@ -87,7 +87,7 @@ class NotebookManager(LoggingConfigurable):
|
|||||||
"""
|
"""
|
||||||
return basename
|
return basename
|
||||||
|
|
||||||
def list_notebooks(self):
|
def list_notebooks(self, path=''):
|
||||||
"""Return a list of notebook dicts without content.
|
"""Return a list of notebook dicts without content.
|
||||||
|
|
||||||
This returns a list of dicts, each of the form::
|
This returns a list of dicts, each of the form::
|
||||||
@ -112,53 +112,51 @@ class NotebookManager(LoggingConfigurable):
|
|||||||
"""Update the notebook model and return the model with no content."""
|
"""Update the notebook model and return the model with no content."""
|
||||||
raise NotImplementedError('must be implemented in a subclass')
|
raise NotImplementedError('must be implemented in a subclass')
|
||||||
|
|
||||||
def delete_notebook_model(self, name, path):
|
def delete_notebook_model(self, name, path=''):
|
||||||
"""Delete notebook by name and path."""
|
"""Delete notebook by name and path."""
|
||||||
raise NotImplementedError('must be implemented in a subclass')
|
raise NotImplementedError('must be implemented in a subclass')
|
||||||
|
|
||||||
def create_notebook_model(self, model=None, path=''):
|
def create_notebook_model(self, model=None, path=''):
|
||||||
"""Create a new untitled notebook and return its model with no content."""
|
"""Create a new untitled notebook and return its model with no content."""
|
||||||
untitled = self.increment_filename('Untitled', path)
|
|
||||||
if model is None:
|
if model is None:
|
||||||
model = {}
|
model = {}
|
||||||
|
if 'content' not in model:
|
||||||
metadata = current.new_metadata(name=u'')
|
metadata = current.new_metadata(name=u'')
|
||||||
nb = current.new_notebook(metadata=metadata)
|
model['content'] = current.new_notebook(metadata=metadata)
|
||||||
model['content'] = nb
|
if 'name' not in model:
|
||||||
model['name'] = name = untitled
|
model['name'] = self.increment_filename('Untitled', path)
|
||||||
model['path'] = path
|
|
||||||
else:
|
model['path'] = path
|
||||||
name = model.setdefault('name', untitled)
|
model = self.save_notebook_model(model, model['name'], model['path'])
|
||||||
model['path'] = path
|
|
||||||
model = self.save_notebook_model(model, name, path)
|
|
||||||
return model
|
return model
|
||||||
|
|
||||||
def copy_notebook(self, name, path='/', content=False):
|
def copy_notebook(self, name, path=''):
|
||||||
"""Copy an existing notebook and return its new model."""
|
"""Copy an existing notebook and return its new model."""
|
||||||
model = self.get_notebook_model(name, path)
|
model = self.get_notebook_model(name, path)
|
||||||
name = os.path.splitext(name)[0] + '-Copy'
|
name = os.path.splitext(name)[0] + '-Copy'
|
||||||
name = self.increment_filename(name, path) + self.filename_ext
|
name = self.increment_filename(name, path) + self.filename_ext
|
||||||
model['name'] = name
|
model['name'] = name
|
||||||
model = self.save_notebook_model(model, name, path, content=content)
|
model = self.save_notebook_model(model, name, path)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
# Checkpoint-related
|
# Checkpoint-related
|
||||||
|
|
||||||
def create_checkpoint(self, name, path='/'):
|
def create_checkpoint(self, name, path=''):
|
||||||
"""Create a checkpoint of the current state of a notebook
|
"""Create a checkpoint of the current state of a notebook
|
||||||
|
|
||||||
Returns a checkpoint_id for the new checkpoint.
|
Returns a checkpoint_id for the new checkpoint.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError("must be implemented in a subclass")
|
raise NotImplementedError("must be implemented in a subclass")
|
||||||
|
|
||||||
def list_checkpoints(self, name, path='/'):
|
def list_checkpoints(self, name, path=''):
|
||||||
"""Return a list of checkpoints for a given notebook"""
|
"""Return a list of checkpoints for a given notebook"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def restore_checkpoint(self, checkpoint_id, name, path='/'):
|
def restore_checkpoint(self, checkpoint_id, name, path=''):
|
||||||
"""Restore a notebook from one of its checkpoints"""
|
"""Restore a notebook from one of its checkpoints"""
|
||||||
raise NotImplementedError("must be implemented in a subclass")
|
raise NotImplementedError("must be implemented in a subclass")
|
||||||
|
|
||||||
def delete_checkpoint(self, checkpoint_id, name, path='/'):
|
def delete_checkpoint(self, checkpoint_id, name, path=''):
|
||||||
"""delete a checkpoint for a notebook"""
|
"""delete a checkpoint for a notebook"""
|
||||||
raise NotImplementedError("must be implemented in a subclass")
|
raise NotImplementedError("must be implemented in a subclass")
|
||||||
|
|
||||||
|
@ -1768,15 +1768,12 @@ var IPython = (function (IPython) {
|
|||||||
|
|
||||||
Notebook.prototype.copy_notebook = function(){
|
Notebook.prototype.copy_notebook = function(){
|
||||||
var path = this.notebookPath();
|
var path = this.notebookPath();
|
||||||
var name = {'name': this.notebook_name}
|
|
||||||
var settings = {
|
var settings = {
|
||||||
processData : false,
|
processData : false,
|
||||||
cache : false,
|
cache : false,
|
||||||
type : "POST",
|
type : "POST",
|
||||||
data: JSON.stringify(name),
|
|
||||||
dataType : "json",
|
|
||||||
success:$.proxy(function (data, status, xhr){
|
success:$.proxy(function (data, status, xhr){
|
||||||
notebook_name = data.name;
|
var notebook_name = data.name;
|
||||||
window.open(utils.url_path_join(
|
window.open(utils.url_path_join(
|
||||||
this._baseProjectUrl,
|
this._baseProjectUrl,
|
||||||
'notebooks',
|
'notebooks',
|
||||||
@ -1787,8 +1784,10 @@ var IPython = (function (IPython) {
|
|||||||
};
|
};
|
||||||
var url = utils.url_path_join(
|
var url = utils.url_path_join(
|
||||||
this._baseProjectUrl,
|
this._baseProjectUrl,
|
||||||
'notebooks',
|
'api/notebooks',
|
||||||
path
|
path,
|
||||||
|
this.notebook_name,
|
||||||
|
'copy'
|
||||||
);
|
);
|
||||||
$.ajax(url,settings);
|
$.ajax(url,settings);
|
||||||
};
|
};
|
||||||
|
@ -312,7 +312,7 @@ var IPython = (function (IPython) {
|
|||||||
var upload_button = $('<button/>').text("Upload")
|
var upload_button = $('<button/>').text("Upload")
|
||||||
.addClass('btn btn-primary btn-mini upload_button')
|
.addClass('btn btn-primary btn-mini upload_button')
|
||||||
.click(function (e) {
|
.click(function (e) {
|
||||||
var nbname = item.find('.item_name > input').attr('value');
|
var nbname = item.find('.item_name > input').val();
|
||||||
var nbformat = item.data('nbformat');
|
var nbformat = item.data('nbformat');
|
||||||
var nbdata = item.data('nbdata');
|
var nbdata = item.data('nbdata');
|
||||||
var content_type = 'application/json';
|
var content_type = 'application/json';
|
||||||
@ -323,8 +323,6 @@ var IPython = (function (IPython) {
|
|||||||
}
|
}
|
||||||
var model = {
|
var model = {
|
||||||
content : JSON.parse(nbdata),
|
content : JSON.parse(nbdata),
|
||||||
name : nbname,
|
|
||||||
path : that.notebookPath()
|
|
||||||
};
|
};
|
||||||
var settings = {
|
var settings = {
|
||||||
processData : false,
|
processData : false,
|
||||||
@ -345,7 +343,8 @@ var IPython = (function (IPython) {
|
|||||||
var url = utils.url_path_join(
|
var url = utils.url_path_join(
|
||||||
that.baseProjectUrl(),
|
that.baseProjectUrl(),
|
||||||
'api/notebooks',
|
'api/notebooks',
|
||||||
that.notebookPath()
|
that.notebookPath(),
|
||||||
|
nbname + '.ipynb'
|
||||||
);
|
);
|
||||||
$.ajax(url, settings);
|
$.ajax(url, settings);
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user