1"""Tornado handlers for the live notebook view. 2 3This is a fork from jupyter/notebook#6.x 4""" 5 6# Copyright (c) Jupyter Development Team. 7# Distributed under the terms of the Modified BSD License. 8 9from jupyter_server.transutils import _i18n 10from jupyter_server.utils import ( 11 ensure_async 12) 13from jupyter_server.base.handlers import path_regex, FilesRedirectHandler 14from jupyter_server.extension.handler import ( 15 ExtensionHandlerMixin, 16 ExtensionHandlerJinjaMixin 17) 18from jupyter_server.base.handlers import JupyterHandler 19from collections import namedtuple 20import os 21from tornado import web, gen 22HTTPError = web.HTTPError 23 24 25def get_frontend_exporters(): 26 from nbconvert.exporters.base import get_export_names, get_exporter 27 28 # name=exporter_name, display=export_from_notebook+extension 29 ExporterInfo = namedtuple('ExporterInfo', ['name', 'display']) 30 31 default_exporters = [ 32 ExporterInfo(name='html', display='HTML (.html)'), 33 ExporterInfo(name='latex', display='LaTeX (.tex)'), 34 ExporterInfo(name='markdown', display='Markdown (.md)'), 35 ExporterInfo(name='notebook', display='Notebook (.ipynb)'), 36 ExporterInfo(name='pdf', display='PDF via LaTeX (.pdf)'), 37 ExporterInfo(name='rst', display='reST (.rst)'), 38 ExporterInfo(name='script', display='Script (.txt)'), 39 ExporterInfo(name='slides', display='Reveal.js slides (.slides.html)') 40 ] 41 42 frontend_exporters = [] 43 for name in get_export_names(): 44 exporter_class = get_exporter(name) 45 exporter_instance = exporter_class() 46 ux_name = getattr(exporter_instance, 'export_from_notebook', None) 47 super_uxname = getattr(super(exporter_class, exporter_instance), 48 'export_from_notebook', None) 49 50 # Ensure export_from_notebook is explicitly defined & not inherited 51 if ux_name is not None and ux_name != super_uxname: 52 display = _i18n('{} ({})'.format(ux_name, 53 exporter_instance.file_extension)) 54 frontend_exporters.append(ExporterInfo(name, display)) 55 56 # Ensure default_exporters are in frontend_exporters if not already 57 # This protects against nbconvert versions lower than 5.5 58 names = set(exporter.name.lower() for exporter in frontend_exporters) 59 for exporter in default_exporters: 60 if exporter.name not in names: 61 frontend_exporters.append(exporter) 62 63 # Protect against nbconvert 5.5.0 64 python_exporter = ExporterInfo(name='python', display='python (.py)') 65 if python_exporter in frontend_exporters: 66 frontend_exporters.remove(python_exporter) 67 68 # Protect against nbconvert 5.4.x 69 template_exporter = ExporterInfo(name='custom', display='custom (.txt)') 70 if template_exporter in frontend_exporters: 71 frontend_exporters.remove(template_exporter) 72 return sorted(frontend_exporters) 73 74 75class NotebookHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler): 76 77 @web.authenticated 78 @gen.coroutine 79 def get(self, path): 80 """get renders the notebook template if a name is given, or 81 redirects to the '/files/' handler if the name is not given.""" 82 path = path.strip('/') 83 cm = self.contents_manager 84 85 # will raise 404 on not found 86 try: 87 model = yield ensure_async(cm.get(path, content=False)) 88 except web.HTTPError as e: 89 if e.status_code == 404 and 'files' in path.split('/'): 90 # 404, but '/files/' in URL, let FilesRedirect take care of it 91 yield FilesRedirectHandler.redirect_to_files(self, path) 92 else: 93 raise 94 if model['type'] != 'notebook': 95 # not a notebook, redirect to files 96 yield FilesRedirectHandler.redirect_to_files(self, path) 97 name = path.rsplit('/', 1)[-1] 98 self.write(self.render_template('notebook.html', 99 notebook_path=path, 100 notebook_name=name, 101 kill_kernel=False, 102 mathjax_url=self.mathjax_url, 103 mathjax_config=self.mathjax_config, 104 get_frontend_exporters=get_frontend_exporters 105 ) 106 ) 107 108# ----------------------------------------------------------------------------- 109# URL to handler mappings 110# ----------------------------------------------------------------------------- 111 112 113default_handlers = [ 114 (r"/notebooks%s" % path_regex, NotebookHandler), 115] 116