is_assignments/a2/code/.venv/lib/python3.10/site-packages/nbclassic/notebookapp.py

347 lines
12 KiB
Python

# coding: utf-8
"""A tornado based Jupyter notebook server."""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
from __future__ import absolute_import, print_function
import os
import gettext
import warnings
from tornado.web import RedirectHandler
import nbclassic
from nbclassic import (
DEFAULT_STATIC_FILES_PATH,
DEFAULT_TEMPLATE_PATH_LIST,
nbclassic_path
)
from nbclassic._version import __version__
from traitlets import (
Unicode, List, Bool, default
)
from jupyter_core.paths import jupyter_path
import jupyter_server
from jupyter_server.base.handlers import FileFindHandler
from jupyter_server.utils import url_path_join
# Try to load Notebook as an extension of the Jupyter Server
from jupyter_server.extension.application import (
ExtensionApp,
ExtensionAppJinjaMixin
)
from jupyter_server.transutils import _i18n
from jupyter_server.serverapp import (
load_handlers
)
from .terminal.handlers import TerminalHandler
from notebook_shim.shim import NotebookConfigShimMixin
from notebook_shim.traits import NotebookAppTraits
# -----------------------------------------------------------------------------
# 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}},
_i18n("Don't open the notebook in a browser after startup.")
)
flags['no-mathjax'] = (
{'NotebookApp': {'enable_mathjax': False}},
"""Disable MathJax
MathJax is the javascript library Jupyter uses to render math/LaTeX. It is
very large, so you may want to disable it if you have a slow internet
connection, or for offline use of the notebook.
When disabled, equations etc. will appear as their untransformed TeX source.
"""
)
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',
'keyfile': 'ServerApp.keyfile',
'certfile': 'ServerApp.certfile',
'client-ca': 'ServerApp.client_ca',
'notebook-dir': 'ServerApp.notebook_dir',
'browser': 'ServerApp.browser',
# 'gateway-url': 'GatewayClient.url',
})
# -----------------------------------------------------------------------------
# NotebookApp
# -----------------------------------------------------------------------------
class NotebookApp(
NotebookConfigShimMixin,
ExtensionAppJinjaMixin,
ExtensionApp,
NotebookAppTraits,
):
name = "nbclassic"
version = __version__
description = _i18n("""The Jupyter HTML Notebook.
This launches a Tornado based HTML Notebook Server that serves up an HTML5/Javascript Notebook client.""")
aliases = aliases
flags = flags
extension_url = "/tree"
subcommands = {}
default_url = Unicode("%s/tree" % nbclassic_path()).tag(config=True)
# Override the default open_Browser trait in ExtensionApp,
# setting it to True.
open_browser = Bool(
True,
help="""Whether to open in a browser after starting.
The specific browser used is platform dependent and
determined by the python standard library `webbrowser`
module, unless it is overridden using the --browser
(ServerApp.browser) configuration option.
"""
).tag(config=True)
# Load configuration from classic notebook config file
# for backwards compatibility
config_file_name = Unicode(
"jupyter_notebook_config",
config=True,
help="Specify a config file to load."
)
static_custom_path = List(Unicode(),
help=_i18n(
"""Path to search for custom.js, css""")
)
@default('static_custom_path')
def _default_static_custom_path(self):
return [
os.path.join(d, 'custom') for d in (
self.config_dir,
DEFAULT_STATIC_FILES_PATH)
]
@property
def template_file_path(self):
"""return extra paths + the default locations"""
return self.extra_template_paths + DEFAULT_TEMPLATE_PATH_LIST
extra_nbextensions_path = List(Unicode(), config=True,
help=_i18n(
"""extra paths to look for Javascript notebook extensions""")
)
@property
def nbextensions_path(self):
"""The path to look for Javascript notebook extensions"""
path = self.extra_nbextensions_path + jupyter_path('nbextensions')
return path
# Local path to static files directory.
static_paths = [DEFAULT_STATIC_FILES_PATH]
# Local path to templates directory.
template_paths = DEFAULT_TEMPLATE_PATH_LIST
@property
def static_paths(self):
"""Rename trait in jupyter_server."""
return [DEFAULT_STATIC_FILES_PATH]
@property
def template_paths(self):
"""Rename trait for Jupyter Server."""
return DEFAULT_TEMPLATE_PATH_LIST
def _prepare_templates(self):
super(NotebookApp, self)._prepare_templates()
# Get translations from notebook package.
base_dir = os.path.dirname(nbclassic.__file__)
nbui = gettext.translation('nbui', localedir=os.path.join(
base_dir, 'nbclassic/i18n'), fallback=True)
self.jinja2_env.install_gettext_translations(nbui, newstyle=False)
self.jinja2_env.globals.update(nbclassic_path=nbclassic_path)
self.jinja2_env.globals.update(nbclassic_tree=url_path_join(self.serverapp.base_url, nbclassic_path(), "tree"))
def _link_jupyter_server_extension(self, serverapp):
# Monkey-patch Jupyter Server's and nbclassic's static path list to include
# the classic notebooks static folder.
def static_file_path_jupyter_server(self):
"""return extra paths + the default location"""
return self.extra_static_paths + [jupyter_server.DEFAULT_STATIC_FILES_PATH, nbclassic.DEFAULT_STATIC_FILES_PATH]
serverapp.__class__.static_file_path = property(
static_file_path_jupyter_server)
def static_file_path_nbclassic(self):
"""return extra paths + the default location"""
# NBExtensions look for classic notebook static files under the `/static/notebook/...`
# URL. Unfortunately, this conflicts with nbclassic's new static endpoints which are
# prefixed with `/static/notebooks`, and therefore, serves these files under
# `/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(nbclassic.DEFAULT_STATIC_FILES_PATH,
"notebook"), nbclassic.DEFAULT_STATIC_FILES_PATH]
self.__class__.static_file_path = property(static_file_path_nbclassic)
return super()._link_jupyter_server_extension(serverapp)
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)
settings = dict(
static_custom_path=self.static_custom_path,
static_handler_args={
# don't cache custom.js
'no_cache_paths': [
url_path_join(
self.serverapp.base_url,
'static',
self.name,
'custom'
)
],
},
ignore_minified_js=self.ignore_minified_js,
mathjax_url=self.mathjax_url,
mathjax_config=self.mathjax_config,
nbextensions_path=self.nbextensions_path,
)
self.settings.update(**settings)
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 /files
# for opening non-ipynb files in edit mode.
handlers.append(
(
rf"/{self.file_url_prefix}/((?!.*\.ipynb($|\?)).*)",
RedirectHandler,
{"url": self.serverapp.base_url+"files/{0}"}
)
)
# Add a redirect from /nbclassic to /nbclassic/tree
# if both notebook>=7 and nbclassic are installed.
if len(nbclassic_path()) > 0:
handlers.append(
(
rf"/nbclassic",
RedirectHandler,
{"url": self.serverapp.base_url+"nbclassic/tree"}
)
)
# load extra services specified by users before default handlers
for service in self.settings['extra_services']:
handlers.extend(load_handlers(service))
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 = []
base_url = self.serverapp.base_url
ujoin = url_path_join
# Add terminal handlers
static_handlers.append(
(ujoin(base_url, r"/terminals/(\w+)"), TerminalHandler, {"name": self.name})
)
static_handlers.append(
# (r"/nbextensions/(?!nbextensions_configurator\/list)(.*)", FileFindHandler, {
(ujoin(base_url, r"/nbextensions/(.*)"), FileFindHandler, {
'path': self.settings['nbextensions_path'],
# don't cache anything in nbextensions
'no_cache_paths': ['/'],
}),
)
static_handlers.append(
(ujoin(base_url, r"/custom/(.*)"), FileFindHandler, {
'path': self.settings['static_custom_path'],
# don't cache anything in nbextensions
'no_cache_paths': ['/'],
}),
)
# Add these static handlers after the Notebook base handlers
# to match the original order of handlers in the classic
# notebook codebase.
base_handlers = load_handlers('jupyter_server.base.handlers')
# The extra two handlers (+2) cover the redirect handler
# and the final 404 handler.
n = len(base_handlers) + 2
# Inject the handlers in the tornado router.
router = self.serverapp.web_app.wildcard_router
core_rules = router.rules[:-n]
final_rules = router.rules[-n:]
router.rules = []
router.add_rules(core_rules)
router.add_rules(static_handlers)
router.add_rules(final_rules)
# -----------------------------------------------------------------------------
# Main entry point
# -----------------------------------------------------------------------------
main = launch_new_instance = NotebookApp.launch_instance