Skip to content

Commit

Permalink
add classic notebook static routes in the proper handler order:
Browse files Browse the repository at this point in the history
  • Loading branch information
Zsailer committed Oct 8, 2021
1 parent 5cd6c86 commit 2c7cbd0
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 120 deletions.
7 changes: 4 additions & 3 deletions nbclassic/nbserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import jupyter_server
from jupyter_server.services.config.manager import ConfigManager
from jupyter_server.utils import url_path_join
from .traits import NotebookAppTraits


Expand Down Expand Up @@ -155,7 +154,8 @@ def static_file_path_jupyter_server(self):
"""return extra paths + the default location"""
return self.extra_static_paths + [jupyter_server.DEFAULT_STATIC_FILES_PATH, notebook.DEFAULT_STATIC_FILES_PATH]

serverapp.__class__.static_file_path = property(static_file_path_jupyter_server)
serverapp.__class__.static_file_path = property(
static_file_path_jupyter_server)

def static_file_path_nbclassic(self):
"""return extra paths + the default location"""
Expand All @@ -165,7 +165,8 @@ def static_file_path_nbclassic(self):
# `/static/notebook/notebooks/...`. This monkey-patch places a new file-finder path
# to nbclassic's static file handlers that drops the extra "notebook".
return self.extra_static_paths + \
[os.path.join(notebook.DEFAULT_STATIC_FILES_PATH, "notebook"), notebook.DEFAULT_STATIC_FILES_PATH]
[os.path.join(notebook.DEFAULT_STATIC_FILES_PATH,
"notebook"), notebook.DEFAULT_STATIC_FILES_PATH]

nbapp.__class__.static_file_path = property(static_file_path_nbclassic)

Expand Down
48 changes: 22 additions & 26 deletions nbclassic/notebook/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,20 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from collections import namedtuple
import os
from tornado import web, gen
HTTPError = web.HTTPError

from jupyter_server.base.handlers import JupyterHandler
from jupyter_server.transutils import _i18n
from jupyter_server.utils import (
ensure_async
)
from jupyter_server.base.handlers import path_regex, FilesRedirectHandler
from jupyter_server.extension.handler import (
ExtensionHandlerMixin,
ExtensionHandlerJinjaMixin
)
from jupyter_server.base.handlers import path_regex, FilesRedirectHandler
from jupyter_server.utils import (
url_path_join,
url_escape,
ensure_async
)
from jupyter_server.transutils import _i18n
from jupyter_server.base.handlers import JupyterHandler
from collections import namedtuple
import os
from tornado import web, gen
HTTPError = web.HTTPError


def get_frontend_exporters():
Expand Down Expand Up @@ -53,7 +50,7 @@ def get_frontend_exporters():
# Ensure export_from_notebook is explicitly defined & not inherited
if ux_name is not None and ux_name != super_uxname:
display = _i18n('{} ({})'.format(ux_name,
exporter_instance.file_extension))
exporter_instance.file_extension))
frontend_exporters.append(ExporterInfo(name, display))

# Ensure default_exporters are in frontend_exporters if not already
Expand All @@ -77,7 +74,6 @@ def get_frontend_exporters():

class NotebookHandler(ExtensionHandlerJinjaMixin, ExtensionHandlerMixin, JupyterHandler):


@web.authenticated
@gen.coroutine
def get(self, path):
Expand All @@ -100,18 +96,18 @@ def get(self, path):
yield FilesRedirectHandler.redirect_to_files(self, path)
name = path.rsplit('/', 1)[-1]
self.write(self.render_template('notebook.html',
notebook_path=path,
notebook_name=name,
kill_kernel=False,
mathjax_url=self.mathjax_url,
mathjax_config=self.mathjax_config,
get_frontend_exporters=get_frontend_exporters
)
)

#-----------------------------------------------------------------------------
notebook_path=path,
notebook_name=name,
kill_kernel=False,
mathjax_url=self.mathjax_url,
mathjax_config=self.mathjax_config,
get_frontend_exporters=get_frontend_exporters
)
)

# -----------------------------------------------------------------------------
# URL to handler mappings
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------


default_handlers = [
Expand Down
118 changes: 67 additions & 51 deletions nbclassic/notebookapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,25 @@
# Distributed under the terms of the Modified BSD License.

from __future__ import absolute_import, print_function
from . import traits
from . import shim

import os
import gettext
import random
import sys
import warnings
import gettext

from jinja2 import Environment, FileSystemLoader
from tornado.web import RedirectHandler

import notebook
from notebook import (
DEFAULT_STATIC_FILES_PATH,
DEFAULT_TEMPLATE_PATH_LIST,
__version__,
)

from traitlets.config import Config
from traitlets.config.application import boolean_flag
from traitlets import (
Dict, Unicode, Integer, List, Bool,
observe, default
Unicode, List, Bool, default
)
from ipython_genutils import py3compat
from jupyter_core.paths import jupyter_path

from jupyter_server.base.handlers import FileFindHandler
Expand All @@ -41,40 +35,36 @@
ExtensionAppJinjaMixin
)

from jupyter_server.log import log_request
from jupyter_server.transutils import _i18n
from jupyter_server.serverapp import (
ServerApp,
random_ports,
load_handlers
)
from jupyter_server.utils import url_path_join as ujoin

from .terminal.handlers import TerminalHandler


#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Module globals
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

_examples = """
jupyter nbclassic # start the notebook
jupyter nbclassic --certfile=mycert.pem # use SSL/TLS certificate
jupyter nbclassic password # enter a password to protect the server
"""

#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Aliases and Flags
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

flags = {}
aliases = {}
flags['no-browser']=(
{'ServerApp' : {'open_browser' : False}},
flags['no-browser'] = (
{'ServerApp': {'open_browser': False}},
_i18n("Don't open the notebook in a browser after startup.")
)
flags['no-mathjax']=(
{'NotebookApp' : {'enable_mathjax' : False}},
flags['no-mathjax'] = (
{'NotebookApp': {'enable_mathjax': False}},
"""Disable MathJax
MathJax is the javascript library Jupyter uses to render math/LaTeX. It is
Expand All @@ -85,30 +75,27 @@
"""
)

flags['allow-root']=(
{'ServerApp' : {'allow_root' : True}},
flags['allow-root'] = (
{'ServerApp': {'allow_root': True}},
_i18n("Allow the notebook to be run from root user.")
)

aliases.update({
'ip': 'ServerApp.ip',
'port': 'ServerApp.port',
'port-retries': 'ServerApp.port_retries',
#'transport': 'KernelManager.transport',
# 'transport': 'KernelManager.transport',
'keyfile': 'ServerApp.keyfile',
'certfile': 'ServerApp.certfile',
'client-ca': 'ServerApp.client_ca',
'notebook-dir': 'ServerApp.notebook_dir',
'browser': 'ServerApp.browser',
#'gateway-url': 'GatewayClient.url',
# 'gateway-url': 'GatewayClient.url',
})

#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# NotebookApp
#-----------------------------------------------------------------------------

from . import shim
from . import traits
# -----------------------------------------------------------------------------


class NotebookApp(
Expand Down Expand Up @@ -144,8 +131,9 @@ class NotebookApp(
).tag(config=True)

static_custom_path = List(Unicode(),
help=_i18n("""Path to search for custom.js, css""")
)
help=_i18n(
"""Path to search for custom.js, css""")
)

@default('static_custom_path')
def _default_static_custom_path(self):
Expand All @@ -156,8 +144,9 @@ def _default_static_custom_path(self):
]

extra_nbextensions_path = List(Unicode(), config=True,
help=_i18n("""extra paths to look for Javascript notebook extensions""")
)
help=_i18n(
"""extra paths to look for Javascript notebook extensions""")
)

@property
def nbextensions_path(self):
Expand Down Expand Up @@ -188,19 +177,23 @@ def _prepare_templates(self):
# Get translations from notebook package.
base_dir = os.path.dirname(notebook.__file__)

nbui = gettext.translation('nbui', localedir=os.path.join(base_dir, 'notebook/i18n'), fallback=True)
nbui = gettext.translation('nbui', localedir=os.path.join(
base_dir, 'notebook/i18n'), fallback=True)
self.jinja2_env.install_gettext_translations(nbui, newstyle=False)

def initialize_settings(self):
"""Add settings to the tornado app."""
if self.ignore_minified_js:
self.log.warning(_i18n("""The `ignore_minified_js` flag is deprecated and no longer works."""))
self.log.warning(_i18n("""Alternatively use `%s` when working on the notebook's Javascript and LESS""") % 'npm run build:watch')
warnings.warn(_i18n("The `ignore_minified_js` flag is deprecated and will be removed in Notebook 6.0"), DeprecationWarning)
self.log.warning(
_i18n("""The `ignore_minified_js` flag is deprecated and no longer works."""))
self.log.warning(_i18n(
"""Alternatively use `%s` when working on the notebook's Javascript and LESS""") % 'npm run build:watch')
warnings.warn(_i18n(
"The `ignore_minified_js` flag is deprecated and will be removed in Notebook 6.0"), DeprecationWarning)

settings = dict(
static_custom_path=self.static_custom_path,
static_handler_args = {
static_handler_args={
# don't cache custom.js
'no_cache_paths': [
url_path_join(
Expand All @@ -220,9 +213,16 @@ def initialize_settings(self):

def initialize_handlers(self):
"""Load the (URL pattern, handler) tuples for each component."""
# Tornado adds two types of "Routers" to the web application, 1) the
# "wildcard" router (for all original handlers given to the __init__ method)
# and 2) the "default" router (for all handlers passed to the add_handlers
# method). The default router is called before the wildcard router.
# This is what allows the extension handlers to be matched before
# the main app handlers.

# Default routes
# Order matters. The first handler to match the URL will handle the request.
handlers = []

# Add a redirect from /notebooks to /edit
# for opening non-ipynb files in edit mode.
handlers.append(
Expand All @@ -240,29 +240,45 @@ def initialize_handlers(self):
handlers.extend(load_handlers('nbclassic.tree.handlers'))
handlers.extend(load_handlers('nbclassic.notebook.handlers'))
handlers.extend(load_handlers('nbclassic.edit.handlers'))
self.handlers.extend(handlers)

# Wildcard routes
# These routes *must* be called after all extensions. To mimic
# the classic notebook server as close as possible, these routes
# need to tbe injected into the wildcard routes.
static_handlers = []

# Add terminal handlers
handlers.append(
static_handlers.append(
(r"/terminals/(\w+)", TerminalHandler)
)

handlers.append(
static_handlers.append(
# (r"/nbextensions/(?!nbextensions_configurator\/list)(.*)", FileFindHandler, {
(r"/nbextensions/(.*)", FileFindHandler, {
'path': self.settings['nbextensions_path'],
'no_cache_paths': ['/'], # don't cache anything in nbextensions
# don't cache anything in nbextensions
'no_cache_paths': ['/'],
}),
)
handlers.append(
static_handlers.append(
(r"/custom/(.*)", FileFindHandler, {
'path': self.settings['static_custom_path'],
'no_cache_paths': ['/'], # don't cache anything in nbextensions
# don't cache anything in nbextensions
'no_cache_paths': ['/'],
}),
)
# Add new handlers to Jupyter server handlers.
self.handlers.extend(handlers)

#-----------------------------------------------------------------------------
# Get the wildcard router
router = self.serverapp.web_app.wildcard_router
# Pop out the last route... this route is the final "catch-all" 404.
last_route = router.rules.pop(-1)
# Add the handlers above
router.add_rules(static_handlers)
# Put the 404 handlers back at the end.
router.rules.append(last_route)

# -----------------------------------------------------------------------------
# Main entry point
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------


main = launch_new_instance = NotebookApp.launch_instance
Loading

0 comments on commit 2c7cbd0

Please sign in to comment.