##// END OF EJS Templates
Add comments
Add comments

File last commit:

r15663:713685fc
r15938:80abfdb4
Show More
handlers.py
288 lines | 10.3 KiB | text/x-python | PythonLexer
Brian E. Granger
Splitting handlers into different files....
r10642 """Tornado handlers for the notebooks web service.
Brian E. Granger
Adding new files.
r10641
Authors:
* Brian Granger
"""
#-----------------------------------------------------------------------------
MinRK
update notebook creation handlers...
r13129 # Copyright (C) 2011 The IPython Development Team
Brian E. Granger
Adding new files.
r10641 #
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 import json
Brian E. Granger
Adding new files.
r10641
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 from tornado import web
Brian E. Granger
Adding new files.
r10641
MinRK
escape URLs in Location headers
r13132 from IPython.html.utils import url_path_join, url_escape
Brian E. Granger
Adding new files.
r10641 from IPython.utils.jsonutil import date_default
Thomas Kluyver
Move notebook URL fragment regexen into IPython.html.base.handlers
r13916 from IPython.html.base.handlers import (IPythonHandler, json_errors,
notebook_path_regex, path_regex,
notebook_name_regex)
Brian E. Granger
Adding new files.
r10641
#-----------------------------------------------------------------------------
# Notebook web service handlers
#-----------------------------------------------------------------------------
Zachary Sailer
manual rebase notebooks web services
r12984
Brian E. Granger
Adding new files.
r10641 class NotebookHandler(IPythonHandler):
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 SUPPORTED_METHODS = (u'GET', u'PUT', u'PATCH', u'POST', u'DELETE')
MinRK
adjust definition of 'path' in notebooks...
r13067 def notebook_location(self, name, path=''):
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 """Return the full URL location of a notebook based.
Parameters
----------
name : unicode
MinRK
adjust definition of 'path' in notebooks...
r13067 The base name of the notebook, such as "foo.ipynb".
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 path : unicode
The URL path of the notebook.
"""
MinRK
escape URLs in Location headers
r13132 return url_escape(url_path_join(
MinRK
s/base_project_url/base_url/...
r15238 self.base_url, 'api', 'notebooks', path, name
MinRK
escape URLs in Location headers
r13132 ))
Brian E. Granger
Adding new files.
r10641
MinRK
update notebook creation handlers...
r13129 def _finish_model(self, model, location=True):
"""Finish a JSON request with a model, setting relevant headers, etc."""
if location:
location = self.notebook_location(model['name'], model['path'])
self.set_header('Location', location)
self.set_header('Last-Modified', model['last_modified'])
self.finish(json.dumps(model, default=date_default))
MinRK
remove notebook read-only view...
r11644 @web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def get(self, path='', name=None):
Brian E. Granger
Adding docstring to NotebookHandler.get.
r13113 """Return a Notebook or list of notebooks.
* GET with path and no notebook name lists notebooks in a directory
* GET with path and notebook name returns notebook JSON
MinRK
adjust definition of 'path' in notebooks...
r13067 """
Brian E. Granger
Adding new files.
r10641 nbm = self.notebook_manager
Zachary Sailer
cleaning nb handlers, adding doc-strings/comments
r13036 # Check to see if a notebook name was given
if name is None:
Brian E. Granger
Addressing review comments....
r15093 # TODO: Remove this after we create the contents web service and directories are
# no longer listed by the notebook web service. This should only handle notebooks
# and not directories.
dirs = nbm.list_dirs(path)
notebooks = []
index = []
for nb in nbm.list_notebooks(path):
if nb['name'].lower() == 'index.ipynb':
index.append(nb)
else:
notebooks.append(nb)
notebooks = index + dirs + notebooks
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 self.finish(json.dumps(notebooks, default=date_default))
MinRK
save before download-as...
r13076 return
# get and return notebook representation
Konrad Hinsen
NotebookManager API: rename *notebook_model methods to *notebook
r15290 model = nbm.get_notebook(name, path)
MinRK
update notebook creation handlers...
r13129 self._finish_model(model, location=False)
Brian E. Granger
Adding new files.
r10641
@web.authenticated
MinRK
adjust definition of 'path' in notebooks...
r13067 @json_errors
def patch(self, path='', name=None):
MinRK
update upload and copy...
r13074 """PATCH renames a notebook without re-uploading content."""
Zachary Sailer
Add 'patch' to session & notebook, rename working
r12997 nbm = self.notebook_manager
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 if name is None:
raise web.HTTPError(400, u'Notebook name missing')
model = self.get_json_body()
if model is None:
raise web.HTTPError(400, u'JSON body missing')
Konrad Hinsen
NotebookManager API: rename *notebook_model methods to *notebook
r15290 model = nbm.update_notebook(model, name, path)
MinRK
update notebook creation handlers...
r13129 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",
path, copy_from,
path, copy_to or '',
)
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
Konrad Hinsen
NotebookManager API: rename *notebook_model methods to *notebook
r15290 model = self.notebook_manager.create_notebook(model, path)
MinRK
update notebook creation handlers...
r13129 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 '')
model = {}
if name:
model['name'] = name
Konrad Hinsen
NotebookManager API: rename *notebook_model methods to *notebook
r15290 model = self.notebook_manager.create_notebook(model, path=path)
MinRK
update notebook creation handlers...
r13129 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)
Konrad Hinsen
NotebookManager API: rename *notebook_model methods to *notebook
r15290 model = self.notebook_manager.save_notebook(model, name, path)
MinRK
update notebook creation handlers...
r13129 if model['path'] != path.strip('/') or model['name'] != name:
# a rename happened, set Location header
location = True
else:
location = False
self._finish_model(model, location)
Zachary Sailer
Add 'patch' to session & notebook, rename working
r12997 @web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def post(self, path='', name=None):
MinRK
update upload and copy...
r13074 """Create a new notebook in the specified path.
MinRK
update notebook creation handlers...
r13129 POST creates new notebooks. The server always decides on the notebook name.
MinRK
update upload and copy...
r13074
Thomas Kluyver
Miscellaneous docs fixes
r13597 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
MinRK
update upload and copy...
r13074 """
MinRK
update notebook creation handlers...
r13129
if name is not None:
MinRK
copy_from in json, not in url param
r13137 raise web.HTTPError(400, "Only POST to directories. Use PUT for full names.")
model = self.get_json_body()
MinRK
update upload and copy...
r13074
MinRK
copy_from in json, not in url param
r13137 if model is not None:
copy_from = model.get('copy_from')
if copy_from:
if model.get('content'):
raise web.HTTPError(400, "Can't upload and copy at the same time.")
self._copy_notebook(copy_from, path)
else:
self._upload_notebook(model, path)
MinRK
update notebook creation handlers...
r13129 else:
self._create_empty_notebook(path)
Zachary Sailer
cleaning nb handlers, adding doc-strings/comments
r13036
@web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def put(self, path='', name=None):
MinRK
update notebook creation handlers...
r13129 """Saves the notebook in the location specified by name and path.
Thomas Kluyver
Miscellaneous docs fixes
r13597 PUT is very similar to POST, but the requester specifies the name,
whereas with POST, the server picks the name.
MinRK
update notebook creation handlers...
r13129
Thomas Kluyver
Miscellaneous docs fixes
r13597 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,
create a new empty notebook.
PUT /api/notebooks/path/Name.ipynb?copy=OtherNotebook.ipynb
Copy OtherNotebook to Name
MinRK
update notebook creation handlers...
r13129 """
if name is None:
raise web.HTTPError(400, "Only PUT to full names. Use POST for directories.")
MinRK
copy_from in json, not in url param
r13137
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 model = self.get_json_body()
MinRK
copy_from in json, not in url param
r13137 if model:
copy_from = model.get('copy_from')
if copy_from:
if model.get('content'):
raise web.HTTPError(400, "Can't upload and copy at the same time.")
self._copy_notebook(copy_from, path, name)
elif self.notebook_manager.notebook_exists(name, path):
MinRK
update notebook creation handlers...
r13129 self._save_notebook(model, path, name)
else:
self._upload_notebook(model, path, name)
else:
self._create_empty_notebook(path, name)
Brian E. Granger
Adding new files.
r10641
@web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def delete(self, path='', name=None):
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 """delete the notebook in the given notebook path"""
Zachary Sailer
manual rebase notebooks web services
r12984 nbm = self.notebook_manager
Konrad Hinsen
NotebookManager API: rename *notebook_model methods to *notebook
r15290 nbm.delete_notebook(name, path)
Brian E. Granger
Adding new files.
r10641 self.set_status(204)
self.finish()
class NotebookCheckpointsHandler(IPythonHandler):
SUPPORTED_METHODS = ('GET', 'POST')
@web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def get(self, path='', name=None):
Brian E. Granger
Adding new files.
r10641 """get lists checkpoints for a notebook"""
nbm = self.notebook_manager
Zachary Sailer
manual rebase notebooks web services
r12984 checkpoints = nbm.list_checkpoints(name, path)
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 data = json.dumps(checkpoints, default=date_default)
Brian E. Granger
Adding new files.
r10641 self.finish(data)
@web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def post(self, path='', name=None):
Brian E. Granger
Adding new files.
r10641 """post creates a new checkpoint"""
nbm = self.notebook_manager
Zachary Sailer
manual rebase notebooks web services
r12984 checkpoint = nbm.create_checkpoint(name, path)
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 data = json.dumps(checkpoint, default=date_default)
MinRK
s/base_project_url/base_url/...
r15238 location = url_path_join(self.base_url, 'api/notebooks',
MinRK
use 'id' for checkpoint ID key...
r13122 path, name, 'checkpoints', checkpoint['id'])
MinRK
escape URLs in Location headers
r13132 self.set_header('Location', url_escape(location))
Thomas Kluyver
Fixes for notebook checkpoint APIs
r13110 self.set_status(201)
Brian E. Granger
Adding new files.
r10641 self.finish(data)
class ModifyNotebookCheckpointsHandler(IPythonHandler):
SUPPORTED_METHODS = ('POST', 'DELETE')
@web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def post(self, path, name, checkpoint_id):
Brian E. Granger
Adding new files.
r10641 """post restores a notebook from a checkpoint"""
nbm = self.notebook_manager
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 nbm.restore_checkpoint(checkpoint_id, name, path)
Brian E. Granger
Adding new files.
r10641 self.set_status(204)
self.finish()
@web.authenticated
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 @json_errors
MinRK
adjust definition of 'path' in notebooks...
r13067 def delete(self, path, name, checkpoint_id):
Brian E. Granger
Adding new files.
r10641 """delete clears a checkpoint for a given notebook"""
nbm = self.notebook_manager
Zachary Sailer
review fixes on tests, add extra kernel api test
r13045 nbm.delete_checkpoint(checkpoint_id, name, path)
Brian E. Granger
Adding new files.
r10641 self.set_status(204)
self.finish()
Zachary Sailer
manual rebase notebooks web services
r12984
Brian E. Granger
More work on the handlers
r10647 #-----------------------------------------------------------------------------
# URL to handler mappings
#-----------------------------------------------------------------------------
_checkpoint_id_regex = r"(?P<checkpoint_id>[\w-]+)"
default_handlers = [
Thomas Kluyver
Move notebook URL fragment regexen into IPython.html.base.handlers
r13916 (r"/api/notebooks%s/checkpoints" % notebook_path_regex, NotebookCheckpointsHandler),
(r"/api/notebooks%s/checkpoints/%s" % (notebook_path_regex, _checkpoint_id_regex),
Zachary Sailer
manual rebase notebooks web services
r12984 ModifyNotebookCheckpointsHandler),
Thomas Kluyver
Move notebook URL fragment regexen into IPython.html.base.handlers
r13916 (r"/api/notebooks%s" % notebook_path_regex, NotebookHandler),
(r"/api/notebooks%s" % path_regex, NotebookHandler),
Brian E. Granger
More work on the handlers
r10647 ]