diff --git a/IPython/html/nbconvert/handlers.py b/IPython/html/nbconvert/handlers.py new file mode 100644 index 000000000..476acfeca --- /dev/null +++ b/IPython/html/nbconvert/handlers.py @@ -0,0 +1,68 @@ +import os + +from tornado import web + +from ..base.handlers import IPythonHandler +from IPython.nbformat.current import to_notebook_json +from IPython.nbconvert.exporters.export import exporter_map +from IPython.utils import tz + + +def has_resource_files(resources): + output_files_dir = resources.get('output_files_dir', "") + return bool(os.path.isdir(output_files_dir) and \ + os.listdir(output_files_dir)) + +class NbconvertFileHandler(IPythonHandler): + + SUPPORTED_METHODS = ('GET',) + + @web.authenticated + def get(self, format, path='', name=None): + exporter = exporter_map[format]() + + path = path.strip('/') + os_path = self.notebook_manager.get_os_path(name, path) + if not os.path.isfile(os_path): + raise web.HTTPError(404, u'Notebook does not exist: %s' % name) + + info = os.stat(os_path) + self.set_header('Last-Modified', tz.utcfromtimestamp(info.st_mtime)) + + output, resources = exporter.from_filename(os_path) + + # TODO: If there are resources, combine them into a zip file + assert not has_resource_files(resources) + + self.finish(output) + +class NbconvertPostHandler(IPythonHandler): + SUPPORTED_METHODS = ('POST',) + + @web.authenticated + def post(self, format): + exporter = exporter_map[format]() + + model = self.get_json_body() + nbnode = to_notebook_json(model['content']) + output, resources = exporter.from_notebook_node(nbnode) + + # TODO: If there are resources, combine them into a zip file + assert not has_resource_files(resources) + + self.finish(output) + +#----------------------------------------------------------------------------- +# URL to handler mappings +#----------------------------------------------------------------------------- + +_format_regex = r"(?P\w+)" +_path_regex = r"(?P(?:/.*)*)" +_notebook_name_regex = r"(?P[^/]+\.ipynb)" +_notebook_path_regex = "%s/%s" % (_path_regex, _notebook_name_regex) + +default_handlers = [ + (r"/nbconvert/%s%s" % (_format_regex, _notebook_path_regex), + NbconvertFileHandler), + (r"/nbconvert/%s" % _format_regex, NbconvertPostHandler), +] \ No newline at end of file diff --git a/IPython/html/notebookapp.py b/IPython/html/notebookapp.py index 5c6850001..c49c8eb4d 100644 --- a/IPython/html/notebookapp.py +++ b/IPython/html/notebookapp.py @@ -192,6 +192,7 @@ class NotebookWebApplication(web.Application): handlers.extend(load_handlers('auth.login')) handlers.extend(load_handlers('auth.logout')) handlers.extend(load_handlers('notebook.handlers')) + handlers.extend(load_handlers('nbconvert.handlers')) handlers.extend(load_handlers('services.kernels.handlers')) handlers.extend(load_handlers('services.notebooks.handlers')) handlers.extend(load_handlers('services.clusters.handlers')) diff --git a/IPython/html/services/notebooks/filenbmanager.py b/IPython/html/services/notebooks/filenbmanager.py index 3ae54ed6a..749892fbc 100644 --- a/IPython/html/services/notebooks/filenbmanager.py +++ b/IPython/html/services/notebooks/filenbmanager.py @@ -178,7 +178,7 @@ class FileNotebookManager(NotebookManager): return notebooks def get_notebook_model(self, name, path='', content=True): - """ Takes a path and name for a notebook and returns it's model + """ Takes a path and name for a notebook and returns its model Parameters ----------